From 645bbe989ba5a93397c737d3107570fd0f42d5ed Mon Sep 17 00:00:00 2001 From: arbee Date: Sat, 1 Apr 2023 19:03:31 -0400 Subject: PortAudio: sync to upstream GitHub revision 0e9b386a1053261340bc8bb32335484ef77b258b [R. Belmont, PortAudio team] * Tested and works on Windows, macOS, and Linux. * Fixes compatibility with macOS Ventura and bugfixes WASAPI and WDM-KS on Windows. --- 3rdparty/portaudio/CMakeLists.txt | 789 +- 3rdparty/portaudio/Makefile.in | 12 +- 3rdparty/portaudio/README.md | 63 + 3rdparty/portaudio/aclocal.m4 | 67 +- 3rdparty/portaudio/bindings/cpp/ChangeLog | 8 +- 3rdparty/portaudio/bindings/cpp/INSTALL | 2 +- 3rdparty/portaudio/bindings/cpp/aclocal.m4 | 2 +- .../portaudio/bindings/cpp/build/gnu/config.guess | 2 +- 3rdparty/portaudio/bindings/cpp/example/devs.cxx | 308 +- 3rdparty/portaudio/bindings/cpp/example/sine.cxx | 206 +- .../cpp/include/portaudiocpp/AsioDeviceAdapter.hxx | 70 +- .../cpp/include/portaudiocpp/AutoSystem.hxx | 84 +- .../cpp/include/portaudiocpp/BlockingStream.hxx | 37 +- .../include/portaudiocpp/CFunCallbackStream.hxx | 45 +- .../cpp/include/portaudiocpp/CallbackInterface.hxx | 56 +- .../cpp/include/portaudiocpp/CallbackStream.hxx | 34 +- .../include/portaudiocpp/CppFunCallbackStream.hxx | 112 +- .../bindings/cpp/include/portaudiocpp/Device.hxx | 121 +- .../DirectionSpecificStreamParameters.hxx | 70 +- .../cpp/include/portaudiocpp/Exception.hxx | 173 +- .../bindings/cpp/include/portaudiocpp/HostApi.hxx | 75 +- .../portaudiocpp/InterfaceCallbackStream.hxx | 38 +- .../include/portaudiocpp/MemFunCallbackStream.hxx | 162 +- .../cpp/include/portaudiocpp/PortAudioCpp.hxx | 38 +- .../cpp/include/portaudiocpp/SampleDataFormat.hxx | 30 +- .../bindings/cpp/include/portaudiocpp/Stream.hxx | 93 +- .../cpp/include/portaudiocpp/StreamParameters.hxx | 110 +- .../bindings/cpp/include/portaudiocpp/System.hxx | 117 +- .../include/portaudiocpp/SystemDeviceIterator.hxx | 71 +- .../include/portaudiocpp/SystemHostApiIterator.hxx | 60 +- .../cpp/source/portaudiocpp/AsioDeviceAdapter.cxx | 106 +- .../cpp/source/portaudiocpp/BlockingStream.cxx | 173 +- .../cpp/source/portaudiocpp/CFunCallbackStream.cxx | 56 +- .../cpp/source/portaudiocpp/CallbackInterface.cxx | 28 +- .../cpp/source/portaudiocpp/CallbackStream.cxx | 24 +- .../source/portaudiocpp/CppFunCallbackStream.cxx | 122 +- .../bindings/cpp/source/portaudiocpp/Device.cxx | 288 +- .../DirectionSpecificStreamParameters.cxx | 308 +- .../bindings/cpp/source/portaudiocpp/Exception.cxx | 232 +- .../bindings/cpp/source/portaudiocpp/HostApi.cxx | 218 +- .../portaudiocpp/InterfaceCallbackStream.cxx | 70 +- .../source/portaudiocpp/MemFunCallbackStream.cxx | 1 - .../bindings/cpp/source/portaudiocpp/Stream.cxx | 366 +- .../cpp/source/portaudiocpp/StreamParameters.cxx | 307 +- .../bindings/cpp/source/portaudiocpp/System.cxx | 571 +- .../source/portaudiocpp/SystemDeviceIterator.cxx | 108 +- .../source/portaudiocpp/SystemHostApiIterator.cxx | 107 +- 3rdparty/portaudio/cmake/PortAudioConfig.cmake.in | 18 + 3rdparty/portaudio/cmake/cmake_uninstall.cmake.in | 21 + 3rdparty/portaudio/cmake/modules/FindASIO.cmake | 79 + 3rdparty/portaudio/cmake/modules/FindJACK.cmake | 67 + 3rdparty/portaudio/cmake/modules/FindOSS.cmake | 57 + 3rdparty/portaudio/cmake/modules/FindRegex.cmake | 68 + 3rdparty/portaudio/cmake/portaudio-2.0.pc.in | 13 + 3rdparty/portaudio/cmake/portaudio.def.in | 67 + .../cmake/toolchains/i686-w64-mingw32.cmake | 17 + 3rdparty/portaudio/configure | 156 +- 3rdparty/portaudio/configure.in | 112 +- 3rdparty/portaudio/doc/src/api_overview.dox | 2 +- 3rdparty/portaudio/doc/src/mainpage.dox | 18 +- .../portaudio/doc/src/tutorial/compile_cmake.dox | 58 +- .../portaudio/doc/src/tutorial/compile_linux.dox | 2 +- .../doc/src/tutorial/compile_mac_coreaudio.dox | 14 +- .../portaudio/doc/src/tutorial/compile_windows.dox | 19 +- .../doc/src/tutorial/compile_windows_asio_msvc.dox | 4 + .../doc/src/tutorial/compile_windows_mingw-w64.dox | 44 + .../doc/src/tutorial/compile_windows_mingw.dox | 8 +- .../doc/src/tutorial/start_stop_abort.dox | 2 +- .../portaudio/doc/src/tutorial/tutorial_start.dox | 10 +- .../doc/src/tutorial/writing_a_callback.dox | 2 +- 3rdparty/portaudio/examples/CMakeLists.txt | 79 +- 3rdparty/portaudio/examples/pa_devs.c | 26 +- 3rdparty/portaudio/examples/pa_fuzz.c | 38 +- .../examples/paex_mono_asio_channel_select.c | 26 +- 3rdparty/portaudio/examples/paex_ocean_shore.c | 58 +- 3rdparty/portaudio/examples/paex_pink.c | 44 +- 3rdparty/portaudio/examples/paex_read_write_wire.c | 25 +- 3rdparty/portaudio/examples/paex_record.c | 27 +- 3rdparty/portaudio/examples/paex_record_file.c | 21 +- 3rdparty/portaudio/examples/paex_saw.c | 18 +- 3rdparty/portaudio/examples/paex_sine.c | 30 +- 3rdparty/portaudio/examples/paex_sine_c++.cpp | 18 +- 3rdparty/portaudio/examples/paex_wmme_ac3.c | 55 +- 3rdparty/portaudio/examples/paex_wmme_surround.c | 97 +- 3rdparty/portaudio/examples/paex_write_sine.c | 44 +- .../portaudio/examples/paex_write_sine_nonint.c | 44 +- 3rdparty/portaudio/include/pa_asio.h | 18 +- 3rdparty/portaudio/include/pa_jack.h | 6 +- 3rdparty/portaudio/include/pa_linux_alsa.h | 6 +- 3rdparty/portaudio/include/pa_mac_core.h | 26 +- 3rdparty/portaudio/include/pa_win_ds.h | 14 +- 3rdparty/portaudio/include/pa_win_wasapi.h | 511 +- 3rdparty/portaudio/include/pa_win_waveformat.h | 162 +- 3rdparty/portaudio/include/pa_win_wdmks.h | 8 +- 3rdparty/portaudio/include/pa_win_wmme.h | 18 +- 3rdparty/portaudio/include/portaudio.h | 148 +- 3rdparty/portaudio/ltmain.sh | 6 +- 3rdparty/portaudio/msvc/portaudio.def | 64 + 3rdparty/portaudio/msvc/portaudio.dsp | 269 + 3rdparty/portaudio/msvc/portaudio.dsw | 29 + 3rdparty/portaudio/msvc/portaudio.sln | 32 + 3rdparty/portaudio/msvc/portaudio.vcproj | 1932 ++++ 3rdparty/portaudio/msvc/readme.txt | 112 + 3rdparty/portaudio/pa_compare_def_files.py | 98 + 3rdparty/portaudio/pa_whitelint.py | 297 + 3rdparty/portaudio/qa/CMakeLists.txt | 5 + 3rdparty/portaudio/qa/loopback/CMakeLists.txt | 19 + .../portaudio/qa/loopback/src/audio_analyzer.c | 901 +- .../portaudio/qa/loopback/src/audio_analyzer.h | 80 +- 3rdparty/portaudio/qa/loopback/src/biquad_filter.c | 147 +- 3rdparty/portaudio/qa/loopback/src/biquad_filter.h | 24 +- 3rdparty/portaudio/qa/loopback/src/paqa.c | 2508 +++-- 3rdparty/portaudio/qa/loopback/src/paqa_tools.c | 222 +- 3rdparty/portaudio/qa/loopback/src/paqa_tools.h | 6 +- 3rdparty/portaudio/qa/loopback/src/qa_tools.h | 48 +- .../qa/loopback/src/test_audio_analyzer.c | 982 +- .../qa/loopback/src/test_audio_analyzer.h | 6 +- 3rdparty/portaudio/qa/loopback/src/write_wav.c | 104 +- 3rdparty/portaudio/qa/loopback/src/write_wav.h | 14 +- 3rdparty/portaudio/qa/paqa_devs.c | 220 +- 3rdparty/portaudio/qa/paqa_errs.c | 34 +- 3rdparty/portaudio/qa/paqa_latency.c | 80 +- 3rdparty/portaudio/src/common/pa_allocation.c | 26 +- 3rdparty/portaudio/src/common/pa_allocation.h | 17 +- 3rdparty/portaudio/src/common/pa_converters.c | 172 +- 3rdparty/portaudio/src/common/pa_converters.h | 18 +- 3rdparty/portaudio/src/common/pa_cpuload.c | 8 +- 3rdparty/portaudio/src/common/pa_cpuload.h | 8 +- 3rdparty/portaudio/src/common/pa_debugprint.c | 50 +- 3rdparty/portaudio/src/common/pa_debugprint.h | 16 +- 3rdparty/portaudio/src/common/pa_dither.c | 90 +- 3rdparty/portaudio/src/common/pa_dither.h | 6 +- 3rdparty/portaudio/src/common/pa_endianness.h | 36 +- 3rdparty/portaudio/src/common/pa_front.c | 50 +- 3rdparty/portaudio/src/common/pa_gitrevision.h | 2 +- 3rdparty/portaudio/src/common/pa_hostapi.h | 78 +- 3rdparty/portaudio/src/common/pa_memorybarrier.h | 80 +- 3rdparty/portaudio/src/common/pa_process.c | 360 +- 3rdparty/portaudio/src/common/pa_process.h | 68 +- 3rdparty/portaudio/src/common/pa_ringbuffer.c | 14 +- 3rdparty/portaudio/src/common/pa_ringbuffer.h | 18 +- 3rdparty/portaudio/src/common/pa_stream.c | 6 +- 3rdparty/portaudio/src/common/pa_stream.h | 10 +- 3rdparty/portaudio/src/common/pa_trace.c | 12 +- 3rdparty/portaudio/src/common/pa_trace.h | 16 +- 3rdparty/portaudio/src/common/pa_types.h | 8 +- 3rdparty/portaudio/src/common/pa_util.h | 28 +- .../portaudio/src/hostapi/alsa/pa_linux_alsa.c | 205 +- .../portaudio/src/hostapi/asihpi/pa_linux_asihpi.c | 73 +- .../portaudio/src/hostapi/asio/ASIO-README.txt | 33 +- 3rdparty/portaudio/src/hostapi/asio/pa_asio.cpp | 422 +- .../src/hostapi/audioio/pa_unix_audioio.c | 1121 +++ 3rdparty/portaudio/src/hostapi/coreaudio/notes.txt | 4 +- .../portaudio/src/hostapi/coreaudio/pa_mac_core.c | 2923 +++--- .../src/hostapi/coreaudio/pa_mac_core_blocking.c | 733 +- .../src/hostapi/coreaudio/pa_mac_core_blocking.h | 22 +- .../src/hostapi/coreaudio/pa_mac_core_internal.h | 37 +- .../src/hostapi/coreaudio/pa_mac_core_old.c | 913 -- .../src/hostapi/coreaudio/pa_mac_core_utilities.c | 883 +- .../src/hostapi/coreaudio/pa_mac_core_utilities.h | 116 +- 3rdparty/portaudio/src/hostapi/dsound/pa_win_ds.c | 323 +- .../src/hostapi/dsound/pa_win_ds_dynlink.c | 12 +- .../src/hostapi/dsound/pa_win_ds_dynlink.h | 12 +- 3rdparty/portaudio/src/hostapi/jack/pa_jack.c | 145 +- 3rdparty/portaudio/src/hostapi/oss/pa_unix_oss.c | 181 +- 3rdparty/portaudio/src/hostapi/oss/recplay.c | 2 +- .../src/hostapi/skeleton/pa_hostapi_skeleton.c | 78 +- .../wasapi/mingw-include/AudioSessionTypes.h | 58 + .../src/hostapi/wasapi/mingw-include/PropIdl.h | 19 + .../src/hostapi/wasapi/mingw-include/ShTypes.h | 359 + .../src/hostapi/wasapi/mingw-include/audioclient.h | 5 +- .../wasapi/mingw-include/functiondiscoverykeys.h | 2 +- .../mingw-include/functiondiscoverykeys_devpkey.h | 13 + .../src/hostapi/wasapi/mingw-include/ksproxy.h | 1 - .../src/hostapi/wasapi/mingw-include/propkey.h | 13 + .../src/hostapi/wasapi/mingw-include/sdkddkver.h | 220 + .../hostapi/wasapi/mingw-include/winapifamily.h | 24 + .../portaudio/src/hostapi/wasapi/pa_win_wasapi.c | 9912 +++++++++++--------- .../portaudio/src/hostapi/wdmks/pa_win_wdmks.c | 319 +- 3rdparty/portaudio/src/hostapi/wdmks/readme.txt | 2 +- 3rdparty/portaudio/src/hostapi/wmme/pa_win_wmme.c | 634 +- 3rdparty/portaudio/src/os/unix/pa_unix_hostapis.c | 13 +- 3rdparty/portaudio/src/os/unix/pa_unix_util.c | 55 +- 3rdparty/portaudio/src/os/unix/pa_unix_util.h | 22 +- .../portaudio/src/os/win/pa_win_coinitialize.c | 47 +- .../portaudio/src/os/win/pa_win_coinitialize.h | 18 +- 3rdparty/portaudio/src/os/win/pa_win_hostapis.c | 15 +- 3rdparty/portaudio/src/os/win/pa_win_util.c | 49 +- 3rdparty/portaudio/src/os/win/pa_win_util.h | 64 + 3rdparty/portaudio/src/os/win/pa_win_waveformat.c | 113 +- 3rdparty/portaudio/src/os/win/pa_win_wdmks_utils.c | 42 +- 3rdparty/portaudio/src/os/win/pa_win_wdmks_utils.h | 10 +- .../portaudio/src/os/win/pa_x86_plain_converters.c | 114 +- .../portaudio/src/os/win/pa_x86_plain_converters.h | 6 +- 3rdparty/portaudio/test/CMakeLists.txt | 66 +- 3rdparty/portaudio/test/pa_minlat.c | 72 +- 3rdparty/portaudio/test/patest1.c | 88 +- 3rdparty/portaudio/test/patest_buffer.c | 26 +- 3rdparty/portaudio/test/patest_callbackstop.c | 80 +- 3rdparty/portaudio/test/patest_clip.c | 28 +- 3rdparty/portaudio/test/patest_converters.c | 37 +- 3rdparty/portaudio/test/patest_dither.c | 34 +- .../test/patest_dsound_find_best_latency_params.c | 76 +- .../test/patest_dsound_low_level_latency_params.c | 53 +- 3rdparty/portaudio/test/patest_dsound_surround.c | 91 +- 3rdparty/portaudio/test/patest_hang.c | 34 +- 3rdparty/portaudio/test/patest_in_overflow.c | 34 +- 3rdparty/portaudio/test/patest_jack_wasapi.c | 446 +- 3rdparty/portaudio/test/patest_latency.c | 22 +- 3rdparty/portaudio/test/patest_leftright.c | 74 +- 3rdparty/portaudio/test/patest_longsine.c | 20 +- 3rdparty/portaudio/test/patest_many.c | 18 +- 3rdparty/portaudio/test/patest_maxsines.c | 28 +- 3rdparty/portaudio/test/patest_mono.c | 23 +- 3rdparty/portaudio/test/patest_multi_sine.c | 24 +- 3rdparty/portaudio/test/patest_out_underflow.c | 38 +- 3rdparty/portaudio/test/patest_prime.c | 34 +- 3rdparty/portaudio/test/patest_read_record.c | 31 +- 3rdparty/portaudio/test/patest_ringmix.c | 14 +- 3rdparty/portaudio/test/patest_sine8.c | 18 +- 3rdparty/portaudio/test/patest_sine_channelmaps.c | 28 +- 3rdparty/portaudio/test/patest_sine_formats.c | 14 +- 3rdparty/portaudio/test/patest_sine_srate.c | 62 +- 3rdparty/portaudio/test/patest_sine_time.c | 117 +- 3rdparty/portaudio/test/patest_start_stop.c | 30 +- 3rdparty/portaudio/test/patest_stop.c | 40 +- 3rdparty/portaudio/test/patest_stop_playout.c | 52 +- .../test/patest_suggested_vs_streaminfo_latency.c | 42 +- .../test/patest_suggested_vs_streaminfo_latency.py | 8 +- 3rdparty/portaudio/test/patest_sync.c | 60 +- 3rdparty/portaudio/test/patest_timing.c | 28 +- 3rdparty/portaudio/test/patest_toomanysines.c | 60 +- 3rdparty/portaudio/test/patest_two_rates.c | 74 +- 3rdparty/portaudio/test/patest_underflow.c | 20 +- 3rdparty/portaudio/test/patest_unplug.c | 20 +- 3rdparty/portaudio/test/patest_wire.c | 34 +- .../test/patest_wmme_find_best_latency_params.c | 74 +- .../test/patest_wmme_low_level_latency_params.c | 53 +- 3rdparty/portaudio/test/patest_write_stop.c | 30 +- .../test/patest_write_stop_hang_illegal.c | 12 +- 3rdparty/portaudio/vcpkg.json | 38 + scripts/src/3rdparty.lua | 5 - 242 files changed, 23514 insertions(+), 17284 deletions(-) create mode 100644 3rdparty/portaudio/README.md create mode 100644 3rdparty/portaudio/cmake/PortAudioConfig.cmake.in create mode 100644 3rdparty/portaudio/cmake/cmake_uninstall.cmake.in create mode 100644 3rdparty/portaudio/cmake/modules/FindASIO.cmake create mode 100644 3rdparty/portaudio/cmake/modules/FindJACK.cmake create mode 100644 3rdparty/portaudio/cmake/modules/FindOSS.cmake create mode 100644 3rdparty/portaudio/cmake/modules/FindRegex.cmake create mode 100644 3rdparty/portaudio/cmake/portaudio-2.0.pc.in create mode 100644 3rdparty/portaudio/cmake/portaudio.def.in create mode 100644 3rdparty/portaudio/cmake/toolchains/i686-w64-mingw32.cmake create mode 100644 3rdparty/portaudio/doc/src/tutorial/compile_windows_mingw-w64.dox create mode 100644 3rdparty/portaudio/msvc/portaudio.def create mode 100644 3rdparty/portaudio/msvc/portaudio.dsp create mode 100644 3rdparty/portaudio/msvc/portaudio.dsw create mode 100644 3rdparty/portaudio/msvc/portaudio.sln create mode 100644 3rdparty/portaudio/msvc/portaudio.vcproj create mode 100644 3rdparty/portaudio/msvc/readme.txt create mode 100644 3rdparty/portaudio/pa_compare_def_files.py create mode 100644 3rdparty/portaudio/pa_whitelint.py create mode 100644 3rdparty/portaudio/qa/CMakeLists.txt create mode 100644 3rdparty/portaudio/qa/loopback/CMakeLists.txt create mode 100644 3rdparty/portaudio/src/hostapi/audioio/pa_unix_audioio.c delete mode 100644 3rdparty/portaudio/src/hostapi/coreaudio/pa_mac_core_old.c create mode 100644 3rdparty/portaudio/src/hostapi/wasapi/mingw-include/AudioSessionTypes.h create mode 100644 3rdparty/portaudio/src/hostapi/wasapi/mingw-include/PropIdl.h create mode 100644 3rdparty/portaudio/src/hostapi/wasapi/mingw-include/ShTypes.h create mode 100644 3rdparty/portaudio/src/hostapi/wasapi/mingw-include/functiondiscoverykeys_devpkey.h create mode 100644 3rdparty/portaudio/src/hostapi/wasapi/mingw-include/propkey.h create mode 100644 3rdparty/portaudio/src/hostapi/wasapi/mingw-include/sdkddkver.h create mode 100644 3rdparty/portaudio/src/hostapi/wasapi/mingw-include/winapifamily.h create mode 100644 3rdparty/portaudio/src/os/win/pa_win_util.h create mode 100644 3rdparty/portaudio/vcpkg.json mode change 100644 => 100755 scripts/src/3rdparty.lua diff --git a/3rdparty/portaudio/CMakeLists.txt b/3rdparty/portaudio/CMakeLists.txt index 789671a965b..3d81062882d 100644 --- a/3rdparty/portaudio/CMakeLists.txt +++ b/3rdparty/portaudio/CMakeLists.txt @@ -1,408 +1,441 @@ -# $Id: $ +cmake_minimum_required(VERSION 3.1.0) +project(PortAudio VERSION 19.8) + # -# For a "How-To" please refer to the Portaudio documentation at: -# http://www.portaudio.com/trac/wiki/TutorialDir/Compile/CMake +# General PortAudio stuff # -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 +option(PA_BUILD_SHARED_LIBS "Build dynamic library" ${BUILD_SHARED_LIBS}) +option(PA_BUILD_TESTS "Include test projects" OFF) +option(PA_BUILD_EXAMPLES "Include example projects" OFF) + +if(PA_BUILD_SHARED_LIBS) + set(LIBRARY_BUILD_TYPE SHARED) +else() + set(LIBRARY_BUILD_TYPE STATIC) +endif() + +add_library(PortAudio + ${LIBRARY_BUILD_TYPE} + src/common/pa_allocation.c src/common/pa_allocation.h + src/common/pa_converters.c src/common/pa_converters.h + src/common/pa_cpuload.c src/common/pa_cpuload.h + src/common/pa_debugprint.c src/common/pa_debugprint.h + src/common/pa_dither.c src/common/pa_dither.h src/common/pa_endianness.h + src/common/pa_front.c src/common/pa_hostapi.h src/common/pa_memorybarrier.h + src/common/pa_process.c src/common/pa_process.h + src/common/pa_ringbuffer.c src/common/pa_ringbuffer.h + src/common/pa_stream.c src/common/pa_stream.h + src/common/pa_trace.c 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 +include(GNUInstallDirs) + +target_include_directories(PortAudio PUBLIC + $ + $ + $ ) +if(UNIX) + target_compile_options(PortAudio PRIVATE -fPIC) +endif() -SOURCE_GROUP("common" FILES ${PA_COMMON_INCLUDES} ${PA_COMMON_SOURCES}) +set(PORTAUDIO_PUBLIC_HEADERS include/portaudio.h) -SET(PA_PUBLIC_INCLUDES include/portaudio.h) +find_package(Threads REQUIRED) +target_link_libraries(PortAudio PRIVATE Threads::Threads) -SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake_support) +option(PA_ENABLE_DEBUG_OUTPUT "Enable debug output for Portaudio" OFF) +if(PA_ENABLE_DEBUG_OUTPUT) + target_compile_definitions(PortAudio PRIVATE PA_ENABLE_DEBUG_OUTPUT) +endif() -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}) +include(TestBigEndian) +TEST_BIG_ENDIAN(IS_BIG_ENDIAN) +if(IS_BIG_ENDIAN) + target_compile_definitions(PortAudio PRIVATE PA_BIG_ENDIAN) +else() + target_compile_definitions(PortAudio PRIVATE PA_LITTLE_ENDIAN) +endif() + +if(WIN32 AND MSVC AND PA_BUILD_SHARED_LIBS + # 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 override + # that project's global settings. + AND "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_LIST_DIR}") + 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() -IF(WIN32) - SET(PA_PRIVATE_COMPILE_DEFINITIONS ${PA_PRIVATE_COMPILE_DEFINITIONS} _CRT_SECURE_NO_WARNINGS) +# +# Host APIs +# - SET(PA_PLATFORM_SOURCES +option(PA_USE_SKELETON "Use skeleton host API" OFF) +if(PA_USE_SKELETON) + target_sources(PortAudio PRIVATE src/hostapi/skeleton/pa_hostapi_skeleton.c) + target_compile_definitions(PortAudio PRIVATE PA_USE_SKELETON=1) +endif() + +include(CMakeDependentOption) +set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") + +# JACK is most commonly used on Linux, but it is cross platform, so allow building it on any OS +# if the FindJACK.cmake module finds POSIX headers. +find_package(JACK) +cmake_dependent_option(PA_USE_JACK "Enable support for JACK Audio Connection Kit" ON JACK_FOUND OFF) +if(PA_USE_JACK) + target_link_libraries(PortAudio PRIVATE JACK::jack) + target_sources(PortAudio PRIVATE src/hostapi/jack/pa_jack.c) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_jack.h) + target_compile_definitions(PortAudio PUBLIC PA_USE_JACK=1) + set(PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS} -DPA_USE_JACK=1") + set(PKGCONFIG_REQUIRES_PRIVATE "${PKGCONFIG_REQUIRES_PRIVATE} jack") + + # needed for PortAudioConfig.cmake so `find_package(PortAudio)` works in downstream projects + install(FILES cmake/modules/FindRegex.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/portaudio/modules") + install(FILES cmake/modules/FindJACK.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/portaudio/modules") +endif() + +if(WIN32) + target_sources(PortAudio PRIVATE + src/os/win/pa_win_coinitialize.c + src/os/win/pa_win_coinitialize.h src/os/win/pa_win_hostapis.c src/os/win/pa_win_util.c + src/os/win/pa_win_util.h 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() - - SET(PA_PKGCONFIG_LDFLAGS "${PA_PKGCONFIG_LDFLAGS} -lm -lpthread") - SET(PA_LIBRARY_DEPENDENCIES ${PA_LIBRARY_DEPENDENCIES} m pthread) - -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 PRIVATE ${PA_PRIVATE_INCLUDE_PATHS}) -TARGET_INCLUDE_DIRECTORIES(portaudio 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 PRIVATE ${PA_PRIVATE_INCLUDE_PATHS}) -TARGET_INCLUDE_DIRECTORIES(portaudio_static 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() + src/os/win/pa_win_wdmks_utils.h + src/os/win/pa_x86_plain_converters.h + ) + target_include_directories(PortAudio PRIVATE src/os/win) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_win_waveformat.h) + target_link_libraries(PortAudio PRIVATE winmm) + + if(MSVC) + target_sources(PortAudio PRIVATE src/os/win/pa_x86_plain_converters.c) + else() + target_compile_definitions(PortAudio PRIVATE _WIN32_WINNT=0x0501 WINVER=0x0501) + set(DEF_EXCLUDE_X86_PLAIN_CONVERTERS ";") + endif() + + target_compile_definitions(PortAudio PRIVATE _CRT_SECURE_NO_WARNINGS) + + option(PA_USE_ASIO "Enable support for ASIO" OFF) + if(PA_USE_ASIO) + find_package(ASIO) + # Automatically download the ASIO SDK ZIP if it is not found. The ASIO SDK license + # allows for downloading it from Steinberg and using it without charge, but it is + # not allowed to be redistributed. + # + # The file(ARCHIVE_EXTRACT) command needed to extract the ZIP archive was added in + # CMake 3.18, so do not bother downloading the ZIP archive for older CMake versions. + # Instead, FindASIO.cmake directs the user to manually extract the ZIP file to + # CMAKE_PREFIX_PATH or CMAKE_CURRENT_BINARY_DIR. + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.18 AND NOT TARGET ASIO::host) + if(NOT ASIO_SDK_ZIP_PATH) + set(ASIO_SDK_ZIP_PATH "${CMAKE_CURRENT_BINARY_DIR}/asiosdk.zip") + endif() + message(STATUS "Downloading ASIO SDK... ${ASIO_SDK_ZIP_PATH}") + file(DOWNLOAD "https://www.steinberg.net/asiosdk" + "${ASIO_SDK_ZIP_PATH}" + STATUS ASIO_DOWNLOAD_STATUS + SHOW_PROGRESS + ) + if("${ASIO_DOWNLOAD_STATUS}" EQUAL 0) + find_package(ASIO) + else() + list(GET "${ASIO_DOWNLOAD_STATUS}" 1 DOWNLOAD_ERROR) + message(FATAL_ERROR "Error downloading ASIO SDK: ${DOWNLOAD_ERROR} " + "Reconfigure CMake with -DPA_USE_ASIO=OFF to build without ASIO. " + "Alternatively, download the ZIP from https://www.steinberg.net/asiosdk " + "and put it in ${CMAKE_PREFIX_PATH} or ${CMAKE_CURRENT_BINARY_DIR}" + ) + endif() + endif() + endif() + if(PA_USE_ASIO AND TARGET ASIO::host) + target_link_libraries(PortAudio PRIVATE "$") + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_asio.h) + target_compile_definitions(PortAudio PUBLIC PA_USE_ASIO=1) + set(PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS} -DPA_USE_ASIO=1") + target_sources(PortAudio PRIVATE + src/hostapi/asio/pa_asio.cpp + src/hostapi/asio/iasiothiscallresolver.cpp + src/hostapi/asio/iasiothiscallresolver.h + ) + else() + set(DEF_EXCLUDE_ASIO_SYMBOLS ";") + endif() + + option(PA_USE_DS "Enable support for DirectSound" ON) + if(PA_USE_DS) + target_sources(PortAudio PRIVATE + src/hostapi/dsound/pa_win_ds.c + src/hostapi/dsound/pa_win_ds_dynlink.c + src/hostapi/dsound/pa_win_ds_dynlink.h + ) + target_include_directories(PortAudio PRIVATE src/hostapi/dsound) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_win_ds.h) + target_compile_definitions(PortAudio PUBLIC PA_USE_DS=1) + set(PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS} -DPA_USE_DS=1") + target_link_libraries(PortAudio PRIVATE dsound) + if(NOT MINGW) + target_compile_definitions(PortAudio PRIVATE PAWIN_USE_DIRECTSOUNDFULLDUPLEXCREATE) + endif() + endif() + + option(PA_USE_WMME "Enable support for WMME" ON) + if(PA_USE_WMME) + target_sources(PortAudio PRIVATE src/hostapi/wmme/pa_win_wmme.c) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_win_wmme.h) + target_compile_definitions(PortAudio PUBLIC PA_USE_WMME=1) + set(PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS} -DPA_USE_WMME=1") + target_link_libraries(PortAudio PRIVATE ole32 uuid) + else() + set(DEF_EXCLUDE_WMME_SYMBOLS ";") + endif() + + option(PA_USE_WASAPI "Enable support for WASAPI" ON) + if(PA_USE_WASAPI) + target_sources(PortAudio PRIVATE src/hostapi/wasapi/pa_win_wasapi.c) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_win_wasapi.h) + target_compile_definitions(PortAudio PUBLIC PA_USE_WASAPI=1) + set(PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS} -DPA_USE_WASAPI=1") + target_link_libraries(PortAudio PRIVATE ole32 uuid) + else() + set(DEF_EXCLUDE_WASAPI_SYMBOLS ";") + endif() + + option(PA_USE_WDMKS "Enable support for WDMKS" ON) + if(PA_USE_WDMKS) + target_sources(PortAudio PRIVATE + src/os/win/pa_win_wdmks_utils.c + src/hostapi/wdmks/pa_win_wdmks.c + ) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_win_wdmks.h) + target_compile_definitions(PortAudio PUBLIC PA_USE_WDMKS=1) + set(PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS} -DPA_USE_WDMKS=1") + target_link_libraries(PortAudio PRIVATE setupapi ole32 uuid) + endif() + + option(PA_USE_WDMKS_DEVICE_INFO "Use WDM/KS API for device info" ON) + if(PA_USE_WDMKS_DEVICE_INFO) + target_compile_definitions(PortAudio PRIVATE PAWIN_USE_WDMKS_DEVICE_INFO) + endif() + + if(PA_BUILD_SHARED_LIBS) + configure_file(cmake/portaudio.def.in "${CMAKE_CURRENT_BINARY_DIR}/portaudio.def" @ONLY) + target_sources(PortAudio PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/portaudio.def") + endif() +elseif(UNIX) + target_sources(PortAudio PRIVATE + src/os/unix/pa_unix_hostapis.c + src/os/unix/pa_unix_util.c + src/os/unix/pa_unix_util.h + ) + target_include_directories(PortAudio PRIVATE src/os/unix) + target_link_libraries(PortAudio PRIVATE m) + set(PKGCONFIG_LDFLAGS_PRIVATE "${PKGCONFIG_LDFLAGS_PUBLIC} -lm -lpthread") + set(PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS} -pthread") + + if(APPLE) + set(CMAKE_MACOSX_RPATH 1) + target_sources(PortAudio PRIVATE + src/hostapi/coreaudio/pa_mac_core.c + src/hostapi/coreaudio/pa_mac_core_blocking.c + src/hostapi/coreaudio/pa_mac_core_blocking.h + src/hostapi/coreaudio/pa_mac_core_internal.h + src/hostapi/coreaudio/pa_mac_core_utilities.c + src/hostapi/coreaudio/pa_mac_core_utilities.h + ) + target_include_directories(PortAudio PRIVATE src/hostapi/coreaudio) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_mac_core.h) + + find_library(COREAUDIO_LIBRARY CoreAudio REQUIRED) + find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox REQUIRED) + find_library(AUDIOUNIT_LIBRARY AudioUnit REQUIRED) + find_library(COREFOUNDATION_LIBRARY CoreFoundation REQUIRED) + find_library(CORESERVICES_LIBRARY CoreServices REQUIRED) + target_link_libraries(PortAudio PRIVATE + "${COREAUDIO_LIBRARY}" + "${AUDIOTOOLBOX_LIBRARY}" + "${AUDIOUNIT_LIBRARY}" + "${COREFOUNDATION_LIBRARY}" + "${CORESERVICES_LIBRARY}" + ) + target_compile_definitions(PortAudio PUBLIC PA_USE_COREAUDIO=1) + set(PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS} -DPA_USE_COREAUDIO=1") + + # Use C11 so that we can make use of atomic library and avoid deprecation errors. + set_property(TARGET PortAudio PROPERTY C_STANDARD 11) + + set(PKGCONFIG_LDFLAGS_PRIVATE + "${PKGCONFIG_LDFLAGS_PRIVATE} -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreFoundation -framework CoreServices") + else() + # Some BSDs have a reimplementation of alsalib, so do not explicitly check for Linux. + find_package(ALSA) + cmake_dependent_option(PA_USE_ALSA "Enable support for ALSA" ON ALSA_FOUND OFF) + if(PA_USE_ALSA) + target_link_libraries(PortAudio PRIVATE "${ALSA_LIBRARIES}") + target_sources(PortAudio PRIVATE src/hostapi/alsa/pa_linux_alsa.c) + set(PORTAUDIO_PUBLIC_HEADERS "${PORTAUDIO_PUBLIC_HEADERS}" include/pa_linux_alsa.h) + target_compile_definitions(PortAudio PUBLIC PA_USE_ALSA=1) + set(PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS} -DPA_USE_ALSA=1") + + option(PA_ALSA_DYNAMIC "Enable dynamically loading libasound with dlopen using PaAlsa_SetLibraryPathName" OFF) + if(PA_ALSA_DYNAMIC) + target_compile_definitions(PortAudio PRIVATE PA_ALSA_DYNAMIC) + target_link_libraries(PortAudio PRIVATE "${CMAKE_DL_LIBS}") + set(PKGCONFIG_LDFLAGS_PRIVATE "${PKGCONFIG_LDFLAGS_PRIVATE} -l${CMAKE_DL_LIBS}") + else() + set(PKGCONFIG_REQUIRES_PRIVATE "${PKGCONFIG_REQUIRES_PRIVATE} alsa") + endif() + endif() + + # OSS is intentionally off by default to avoid confusing users of PortAudio + # applications. OSS builds but there are no devices available on modern + # Linux systems. + find_package(OSS) + cmake_dependent_option(PA_USE_OSS "Enable support for OSS" OFF "OSS_FOUND" OFF) + if(PA_USE_OSS) + target_sources(PortAudio PRIVATE src/hostapi/oss/pa_unix_oss.c) + target_compile_definitions(PortAudio PUBLIC PA_USE_OSS=1) + set(PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS} -DPA_USE_OSS=1") + target_link_libraries(PortAudio PRIVATE OSS::oss) + # The FindOSS.cmake module does not need to be installed like the JACK modules because it + # does not link any library; it only adds an include directory and compile definition. + endif() + + check_include_file(sys/audioio.h HAVE_SYS_AUDIOIO_H) + cmake_dependent_option(AUDIOIO "Enable support for Solaris/NetBSD audio" ON "HAVE_SYS_AUDIOIO_H" AUDIOIO) + if(AUDIOIO AND HAVE_SYS_AUDIOIO_H) + target_sources(PortAudio PRIVATE src/hostapi/audioio/pa_unix_audioio.c) + target_compile_definitions(PortAudio PUBLIC PA_USE_AUDIOIO=1) + set(PKGCONFIG_CFLAGS "${PKGCONFIG_CFLAGS} -DPA_USE_AUDIOIO=1") + endif() + endif() +endif() + +# Add public headers to sources of PortAudio (used by some IDEs to list them in project tree) +source_group("Public Header Files" FILES ${PORTAUDIO_PUBLIC_HEADERS}) +target_sources(PortAudio PRIVATE ${PORTAUDIO_PUBLIC_HEADERS}) + +# +# Installation +# + +include(CMakePackageConfigHelpers) + +if(NOT CMAKE_FRAMEWORK) + install(FILES README.md DESTINATION "${CMAKE_INSTALL_DOCDIR}/portaudio") + install(FILES LICENSE.txt DESTINATION "${CMAKE_INSTALL_DOCDIR}/portaudio") + + configure_file(cmake/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 "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + + configure_package_config_file(cmake/PortAudioConfig.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/cmake/portaudio/PortAudioConfig.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/portaudio" + NO_CHECK_REQUIRED_COMPONENTS_MACRO + ) + write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/cmake/portaudio/PortAudioConfigVersion.cmake" + VERSION "${PORTAUDIO_VERSION}" + COMPATIBILITY SameMajorVersion + ) + install(EXPORT PortAudio-targets NAMESPACE "PortAudio::" FILE "PortAudioTargets.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/portaudio") + export(TARGETS PortAudio + FILE "${CMAKE_CURRENT_BINARY_DIR}/cmake/portaudio/PortAudioTargets.cmake") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/portaudio/PortAudioConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/cmake/portaudio/PortAudioConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/portaudio") + + if(NOT TARGET uninstall) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") + endif() +endif() + +set_target_properties(PortAudio PROPERTIES + OUTPUT_NAME portaudio + PUBLIC_HEADER "${PORTAUDIO_PUBLIC_HEADERS}" + MACOSX_FRAMEWORK_IDENTIFIER com.portaudio + FRAMEWORK_VERSION A + WINDOWS_EXPORT_ALL_SYMBOLS TRUE + VERSION ${PROJECT_VERSION} + SOVERSION 2 +) +install(TARGETS PortAudio + EXPORT PortAudio-targets + PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + FRAMEWORK DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" +) + +# +# Subdirectories +# +# Some of the tests and examples use private symbols which are not +# exposed by the .def file on Windows. +if(WIN32 AND PA_BUILD_SHARED_LIBS) + set(LINK_PRIVATE_SYMBOLS OFF) +else() + set(LINK_PRIVATE_SYMBOLS ON) +endif() + +if(PA_BUILD_TESTS) + macro(add_test appl_name) + add_executable(${appl_name} "${appl_name}.c") + target_link_libraries(${appl_name} PortAudio Threads::Threads) + if(UNIX) + target_link_libraries(${appl_name} m) + endif() + set_target_properties(${appl_name} + PROPERTIES + FOLDER "Test" + ) + endmacro() + + subdirs(test) + subdirs(qa) +endif() + +if(PA_BUILD_EXAMPLES) + subdirs(examples) +endif() diff --git a/3rdparty/portaudio/Makefile.in b/3rdparty/portaudio/Makefile.in index 5e1a76485ae..ef5f2d85709 100644 --- a/3rdparty/portaudio/Makefile.in +++ b/3rdparty/portaudio/Makefile.in @@ -44,7 +44,7 @@ PALIB = libportaudio.la PAINC = include/portaudio.h PA_LDFLAGS = $(LDFLAGS) $(SHARED_FLAGS) -rpath $(libdir) -no-undefined \ - -export-symbols-regex "(Pa|PaMacCore|PaJack|PaAlsa|PaAsio|PaOSS)_.*" \ + -export-symbols-regex "(Pa|PaMacCore|PaJack|PaAlsa|PaAsio|PaOSS|PaWasapi|PaWasapiWinrt|PaWinMME)_.*" \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) COMMON_OBJS = \ @@ -142,10 +142,12 @@ SRC_DIRS = \ src/hostapi/alsa \ src/hostapi/asihpi \ src/hostapi/asio \ + src/hostapi/audioio \ src/hostapi/coreaudio \ src/hostapi/dsound \ src/hostapi/jack \ src/hostapi/oss \ + src/hostapi/skeleton \ src/hostapi/wasapi \ src/hostapi/wdmks \ src/hostapi/wmme \ @@ -220,16 +222,16 @@ clean: distclean: clean $(RM) config.log config.status Makefile libtool portaudio-2.0.pc -%.o: %.c $(MAKEFILE) $(PAINC) +%.o: %.c $(MAKEFILE) $(PAINC) lib-stamp $(CC) -c $(CFLAGS) $< -o $@ -%.lo: %.c $(MAKEFILE) $(PAINC) +%.lo: %.c $(MAKEFILE) $(PAINC) lib-stamp $(LIBTOOL) --mode=compile $(CC) -c $(CFLAGS) $< -o $@ -%.lo: %.cpp $(MAKEFILE) $(PAINC) +%.lo: %.cpp $(MAKEFILE) $(PAINC) lib-stamp $(LIBTOOL) --mode=compile --tag=CXX $(CXX) -c $(CXXFLAGS) $< -o $@ -%.o: %.cpp $(MAKEFILE) $(PAINC) +%.o: %.cpp $(MAKEFILE) $(PAINC) lib-stamp $(CXX) -c $(CXXFLAGS) $< -o $@ %.o: %.asm diff --git a/3rdparty/portaudio/README.md b/3rdparty/portaudio/README.md new file mode 100644 index 00000000000..cb33144cc12 --- /dev/null +++ b/3rdparty/portaudio/README.md @@ -0,0 +1,63 @@ +# PortAudio - portable audio I/O library + +PortAudio is a portable audio I/O library designed for cross-platform +support of audio. It uses either a callback mechanism to request audio +processing, or blocking read/write calls to buffer data between the +native audio subsystem and the client. Audio can be processed in various +formats, including 32 bit floating point, and will be converted to the +native format internally. + +## Documentation: + +* Documentation is available at http://www.portaudio.com/docs/ +* Or at `/doc/html/index.html` after running Doxygen. +* Also see `src/common/portaudio.h` for the API spec. +* And see the `examples/` and `test/` directories for many examples of usage. (We suggest `examples/paex_saw.c` for an example.) + +For information on compiling programs with PortAudio, please see the +tutorial at: + + http://portaudio.com/docs/v19-doxydocs/tutorial_start.html + +We have an active mailing list for user and developer discussions. +Please feel free to join. See http://www.portaudio.com for details. + +## Important Files and Folders: + + include/portaudio.h = header file for PortAudio API. Specifies API. + src/common/ = platform independent code, host independent + code for all implementations. + src/os = os specific (but host api neutral) code + src/hostapi = implementations for different host apis + + +### Host API Implementations: + + src/hostapi/alsa = Advanced Linux Sound Architecture (ALSA) + src/hostapi/asihpi = AudioScience HPI + src/hostapi/asio = ASIO for Windows and Macintosh + src/hostapi/audioio = /dev/audio (Solaris/NetBSD Audio) + src/hostapi/coreaudio = Macintosh Core Audio for OS X + src/hostapi/dsound = Windows Direct Sound + src/hostapi/jack = JACK Audio Connection Kit + src/hostapi/oss = Unix Open Sound System (OSS) + src/hostapi/wasapi = Windows Vista WASAPI + src/hostapi/wdmks = Windows WDM Kernel Streaming + src/hostapi/wmme = Windows MultiMedia Extensions (MME) + + +### Test Programs: + + test/pa_fuzz.c = guitar fuzz box + test/pa_devs.c = print a list of available devices + test/pa_minlat.c = determine minimum latency for your machine + test/paqa_devs.c = self test that opens all devices + test/paqa_errs.c = test error detection and reporting + test/patest_clip.c = hear a sine wave clipped and unclipped + test/patest_dither.c = hear effects of dithering (extremely subtle) + test/patest_pink.c = fun with pink noise + test/patest_record.c = record and playback some audio + test/patest_maxsines.c = how many sine waves can we play? Tests Pa_GetCPULoad(). + test/patest_sine.c = output a sine wave in a simple PA app + test/patest_sync.c = test synchronization of audio and video + test/patest_wire.c = pass input to output, wire simulator diff --git a/3rdparty/portaudio/aclocal.m4 b/3rdparty/portaudio/aclocal.m4 index 85326befb65..38a96299dd8 100644 --- a/3rdparty/portaudio/aclocal.m4 +++ b/3rdparty/portaudio/aclocal.m4 @@ -649,7 +649,7 @@ configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation -gives unlimited permision to copy, distribute and modify it." +gives unlimited permission to copy, distribute and modify it." while test $[#] != 0 do @@ -1202,7 +1202,7 @@ fi # Invoke $ECHO with all args, space-separated. func_echo_all () { - $ECHO "$*" + $ECHO "$*" } case "$ECHO" in @@ -8542,7 +8542,7 @@ _LT_DECL(, macro_revision, 0) # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. -# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until @@ -8616,7 +8616,7 @@ m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 1 (pkg-config-0.24) -# +# # Copyright © 2004 Scott James Remnant . # # This program is free software; you can redistribute it and/or modify @@ -8669,7 +8669,7 @@ fi[]dnl # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -# only at the first occurence in configure.ac, so if the first place +# only at the first occurrence in configure.ac, so if the first place # it's called might be skipped (such as if it is within an "if", you # have to call PKG_CHECK_EXISTS manually # -------------------------------------------------------------- @@ -8739,7 +8739,7 @@ if test $pkg_failed = yes; then _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` - else + else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs @@ -8774,3 +8774,58 @@ else fi[]dnl ])# PKG_CHECK_MODULES +# This was added to aclocal.m4 because PortAudio ships with configure.in +# and Makefile.in created manually. +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 6 + +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_VAR_IF(CACHEVAR,yes, + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS diff --git a/3rdparty/portaudio/bindings/cpp/ChangeLog b/3rdparty/portaudio/bindings/cpp/ChangeLog index 6b0b02700d9..1e96618ec6b 100644 --- a/3rdparty/portaudio/bindings/cpp/ChangeLog +++ b/3rdparty/portaudio/bindings/cpp/ChangeLog @@ -12,7 +12,7 @@ PortAudioCpp v19 revision 15 (unknown release date): mblaauw: - Changed some exception handling code in HostApi's constructor. - - Added accessors to PortAudio PaStream from PortAudioCpp Stream (their absense being pointed out + - Added accessors to PortAudio PaStream from PortAudioCpp Stream (their absence being pointed out by Tom Jordan). - Fixed a bug/typo in MemFunToCallbackInterfaceAdapter::init() thanks to Fredrik Viklund. - Fixed issue with concrete Stream classes possibly throwing an exception and fixed documentation w.r.t. this. @@ -37,14 +37,14 @@ PortAudioCpp v19 revision 13 03/10/19: the std::exception base class's what() member function (which had throw(), i.e. no-throw guarantee). - Changed the iterators so that they have a set of public typedefs instead of deriving the C++ standard library std::iterator<> struct. G++ 2.95 doesn't support std::exception<> and composition-by-aggregation - is prefered over composition-by-inheritance in this case. + is preferred over composition-by-inheritance in this case. - Changed some minor things to avoid G++ warning messages. mblaauw: - Renamed this file (/WHATSNEW.txt) to /CHANGELOG. - Renamed /PA_ISSUES.txt to /PA_ISSUES. - Added /INSTALL file with some build info for GNU/Linux and VC6. - - Added MSVC 6.0 projects for building PortAudioCpp as a staticly or dynamically linkable library. + - Added MSVC 6.0 projects for building PortAudioCpp as a statically or dynamically linkable library. - Moved build files to /build/(gnu/ or vc6/). - Moved Doxygen configuration files to /doc/ and output to /doc/api_reference/. - Added a /doc/README with some info how to generate Doxygen documentation. @@ -82,7 +82,7 @@ PortAudioCpp v19 revision 09 03/06/25: mblaauw: - Changed some things in SingleDirectionStreamParameters to ease it's usage. - Placed all SingleDirectionStreamParameters stuff into a separate file. - + Totally redid the callback stuff, now it's less ackward and supports C++ functions. + + Totally redid the callback stuff, now it's less awkward and supports C++ functions. PortAudioCpp v19 revision 08 03/06/20: diff --git a/3rdparty/portaudio/bindings/cpp/INSTALL b/3rdparty/portaudio/bindings/cpp/INSTALL index 2099840756e..cde9b495c59 100644 --- a/3rdparty/portaudio/bindings/cpp/INSTALL +++ b/3rdparty/portaudio/bindings/cpp/INSTALL @@ -124,7 +124,7 @@ architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. - On MacOS X 10.5 and later systems, you can create libraries and + On MacOS X 10.6 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like diff --git a/3rdparty/portaudio/bindings/cpp/aclocal.m4 b/3rdparty/portaudio/bindings/cpp/aclocal.m4 index 68c908fbabe..f5dec8f78e0 100644 --- a/3rdparty/portaudio/bindings/cpp/aclocal.m4 +++ b/3rdparty/portaudio/bindings/cpp/aclocal.m4 @@ -657,7 +657,7 @@ configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation -gives unlimited permision to copy, distribute and modify it." +gives unlimited permission to copy, distribute and modify it." while test $[#] != 0 do diff --git a/3rdparty/portaudio/bindings/cpp/build/gnu/config.guess b/3rdparty/portaudio/bindings/cpp/build/gnu/config.guess index 297e5c30f41..d5128acaf10 100644 --- a/3rdparty/portaudio/bindings/cpp/build/gnu/config.guess +++ b/3rdparty/portaudio/bindings/cpp/build/gnu/config.guess @@ -129,7 +129,7 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward diff --git a/3rdparty/portaudio/bindings/cpp/example/devs.cxx b/3rdparty/portaudio/bindings/cpp/example/devs.cxx index 31a560f884e..218042f14c4 100644 --- a/3rdparty/portaudio/bindings/cpp/example/devs.cxx +++ b/3rdparty/portaudio/bindings/cpp/example/devs.cxx @@ -8,44 +8,44 @@ // --------------------------------------------------------------------------------------- void printSupportedStandardSampleRates( - const portaudio::DirectionSpecificStreamParameters &inputParameters, - const portaudio::DirectionSpecificStreamParameters &outputParameters) + const portaudio::DirectionSpecificStreamParameters &inputParameters, + const portaudio::DirectionSpecificStreamParameters &outputParameters) { - static double STANDARD_SAMPLE_RATES[] = { - 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0, - 44100.0, 48000.0, 88200.0, 96000.0, -1 }; // negative terminated list - - int printCount = 0; - - for (int i = 0; STANDARD_SAMPLE_RATES[i] > 0; ++i) - { - portaudio::StreamParameters tmp = portaudio::StreamParameters(inputParameters, outputParameters, STANDARD_SAMPLE_RATES[i], 0, paNoFlag); - - if (tmp.isSupported()) - { - if (printCount == 0) - { - std::cout << " " << STANDARD_SAMPLE_RATES[i]; // 8.2 - printCount = 1; - } - else if (printCount == 4) - { - std::cout << "," << std::endl; - std::cout << " " << STANDARD_SAMPLE_RATES[i]; // 8.2 - printCount = 1; - } - else - { - std::cout << ", " << STANDARD_SAMPLE_RATES[i]; // 8.2 - ++printCount; - } - } - } - - if (printCount == 0) - std::cout << "None" << std::endl; - else - std::cout << std::endl; + static double STANDARD_SAMPLE_RATES[] = { + 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0, + 44100.0, 48000.0, 88200.0, 96000.0, -1 }; // negative terminated list + + int printCount = 0; + + for (int i = 0; STANDARD_SAMPLE_RATES[i] > 0; ++i) + { + portaudio::StreamParameters tmp = portaudio::StreamParameters(inputParameters, outputParameters, STANDARD_SAMPLE_RATES[i], 0, paNoFlag); + + if (tmp.isSupported()) + { + if (printCount == 0) + { + std::cout << " " << STANDARD_SAMPLE_RATES[i]; // 8.2 + printCount = 1; + } + else if (printCount == 4) + { + std::cout << "," << std::endl; + std::cout << " " << STANDARD_SAMPLE_RATES[i]; // 8.2 + printCount = 1; + } + else + { + std::cout << ", " << STANDARD_SAMPLE_RATES[i]; // 8.2 + ++printCount; + } + } + } + + if (printCount == 0) + std::cout << "None" << std::endl; + else + std::cout << std::endl; } // --------------------------------------------------------------------------------------- @@ -53,125 +53,125 @@ void printSupportedStandardSampleRates( int main(int, char*[]); int main(int, char*[]) { - try - { - portaudio::AutoSystem autoSys; - - portaudio::System &sys = portaudio::System::instance(); - - std::cout << "PortAudio version number = " << sys.version() << std::endl; - std::cout << "PortAudio version text = '" << sys.versionText() << "'" << std::endl; - - int numDevices = sys.deviceCount(); - std::cout << "Number of devices = " << numDevices << std::endl; - - for (portaudio::System::DeviceIterator i = sys.devicesBegin(); i != sys.devicesEnd(); ++i) - { - std::cout << "--------------------------------------- device #" << (*i).index() << std::endl; - - // Mark global and API specific default devices: - bool defaultDisplayed = false; - - if ((*i).isSystemDefaultInputDevice()) - { - std::cout << "[ Default Input"; - defaultDisplayed = true; - } - else if ((*i).isHostApiDefaultInputDevice()) - { - std::cout << "[ Default " << (*i).hostApi().name() << " Input"; - defaultDisplayed = true; - } - - if ((*i).isSystemDefaultOutputDevice()) - { - std::cout << (defaultDisplayed ? "," : "["); - std::cout << " Default Output"; - defaultDisplayed = true; - } - else if ((*i).isHostApiDefaultOutputDevice()) - { - std::cout << (defaultDisplayed ? "," : "["); - std::cout << " Default " << (*i).hostApi().name() << " Output"; - defaultDisplayed = true; - } - - if (defaultDisplayed) - std::cout << " ]" << std::endl; - - // Print device info: - std::cout << "Name = " << (*i).name() << std::endl; - std::cout << "Host API = " << (*i).hostApi().name() << std::endl; - std::cout << "Max inputs = " << (*i).maxInputChannels() << ", Max outputs = " << (*i).maxOutputChannels() << std::endl; - - std::cout << "Default low input latency = " << (*i).defaultLowInputLatency() << std::endl; // 8.3 - std::cout << "Default low output latency = " << (*i).defaultLowOutputLatency() << std::endl; // 8.3 - std::cout << "Default high input latency = " << (*i).defaultHighInputLatency() << std::endl; // 8.3 - std::cout << "Default high output latency = " << (*i).defaultHighOutputLatency() << std::endl; // 8.3 + try + { + portaudio::AutoSystem autoSys; + + portaudio::System &sys = portaudio::System::instance(); + + std::cout << "PortAudio version number = " << sys.version() << std::endl; + std::cout << "PortAudio version text = '" << sys.versionText() << "'" << std::endl; + + int numDevices = sys.deviceCount(); + std::cout << "Number of devices = " << numDevices << std::endl; + + for (portaudio::System::DeviceIterator i = sys.devicesBegin(); i != sys.devicesEnd(); ++i) + { + std::cout << "--------------------------------------- device #" << (*i).index() << std::endl; + + // Mark global and API specific default devices: + bool defaultDisplayed = false; + + if ((*i).isSystemDefaultInputDevice()) + { + std::cout << "[ Default Input"; + defaultDisplayed = true; + } + else if ((*i).isHostApiDefaultInputDevice()) + { + std::cout << "[ Default " << (*i).hostApi().name() << " Input"; + defaultDisplayed = true; + } + + if ((*i).isSystemDefaultOutputDevice()) + { + std::cout << (defaultDisplayed ? "," : "["); + std::cout << " Default Output"; + defaultDisplayed = true; + } + else if ((*i).isHostApiDefaultOutputDevice()) + { + std::cout << (defaultDisplayed ? "," : "["); + std::cout << " Default " << (*i).hostApi().name() << " Output"; + defaultDisplayed = true; + } + + if (defaultDisplayed) + std::cout << " ]" << std::endl; + + // Print device info: + std::cout << "Name = " << (*i).name() << std::endl; + std::cout << "Host API = " << (*i).hostApi().name() << std::endl; + std::cout << "Max inputs = " << (*i).maxInputChannels() << ", Max outputs = " << (*i).maxOutputChannels() << std::endl; + + std::cout << "Default low input latency = " << (*i).defaultLowInputLatency() << std::endl; // 8.3 + std::cout << "Default low output latency = " << (*i).defaultLowOutputLatency() << std::endl; // 8.3 + std::cout << "Default high input latency = " << (*i).defaultHighInputLatency() << std::endl; // 8.3 + std::cout << "Default high output latency = " << (*i).defaultHighOutputLatency() << std::endl; // 8.3 #ifdef WIN32 - // ASIO specific latency information: - if ((*i).hostApi().typeId() == paASIO) - { - portaudio::AsioDeviceAdapter asioDevice((*i)); - - std::cout << "ASIO minimum buffer size = " << asioDevice.minBufferSize() << std::endl; - std::cout << "ASIO maximum buffer size = " << asioDevice.maxBufferSize() << std::endl; - std::cout << "ASIO preferred buffer size = " << asioDevice.preferredBufferSize() << std::endl; - - if (asioDevice.granularity() == -1) - std::cout << "ASIO buffer granularity = power of 2" << std::endl; - else - std::cout << "ASIO buffer granularity = " << asioDevice.granularity() << std::endl; - } + // ASIO specific latency information: + if ((*i).hostApi().typeId() == paASIO) + { + portaudio::AsioDeviceAdapter asioDevice((*i)); + + std::cout << "ASIO minimum buffer size = " << asioDevice.minBufferSize() << std::endl; + std::cout << "ASIO maximum buffer size = " << asioDevice.maxBufferSize() << std::endl; + std::cout << "ASIO preferred buffer size = " << asioDevice.preferredBufferSize() << std::endl; + + if (asioDevice.granularity() == -1) + std::cout << "ASIO buffer granularity = power of 2" << std::endl; + else + std::cout << "ASIO buffer granularity = " << asioDevice.granularity() << std::endl; + } #endif // WIN32 - std::cout << "Default sample rate = " << (*i).defaultSampleRate() << std::endl; // 8.2 - - // Poll for standard sample rates: - portaudio::DirectionSpecificStreamParameters inputParameters((*i), (*i).maxInputChannels(), portaudio::INT16, true, 0.0, NULL); - portaudio::DirectionSpecificStreamParameters outputParameters((*i), (*i).maxOutputChannels(), portaudio::INT16, true, 0.0, NULL); - - if (inputParameters.numChannels() > 0) - { - std::cout << "Supported standard sample rates" << std::endl; - std::cout << " for half-duplex 16 bit " << inputParameters.numChannels() << " channel input = " << std::endl; - printSupportedStandardSampleRates(inputParameters, portaudio::DirectionSpecificStreamParameters::null()); - } - - if (outputParameters.numChannels() > 0) - { - std::cout << "Supported standard sample rates" << std::endl; - std::cout << " for half-duplex 16 bit " << outputParameters.numChannels() << " channel output = " << std::endl; - printSupportedStandardSampleRates(portaudio::DirectionSpecificStreamParameters::null(), outputParameters); - } - - if (inputParameters.numChannels() > 0 && outputParameters.numChannels() > 0) - { - std::cout << "Supported standard sample rates" << std::endl; - std::cout << " for full-duplex 16 bit " << inputParameters.numChannels() << " channel input, " << outputParameters.numChannels() << " channel output = " << std::endl; - printSupportedStandardSampleRates(inputParameters, outputParameters); - } - } - - std::cout << "----------------------------------------------" << std::endl; - } - catch (const portaudio::PaException &e) - { - std::cout << "A PortAudio error occured: " << e.paErrorText() << std::endl; - } - catch (const portaudio::PaCppException &e) - { - std::cout << "A PortAudioCpp error occured: " << e.what() << std::endl; - } - catch (const std::exception &e) - { - std::cout << "A generic exception occured: " << e.what() << std::endl; - } - catch (...) - { - std::cout << "An unknown exception occured." << std::endl; - } - - return 0; + std::cout << "Default sample rate = " << (*i).defaultSampleRate() << std::endl; // 8.2 + + // Poll for standard sample rates: + portaudio::DirectionSpecificStreamParameters inputParameters((*i), (*i).maxInputChannels(), portaudio::INT16, true, 0.0, NULL); + portaudio::DirectionSpecificStreamParameters outputParameters((*i), (*i).maxOutputChannels(), portaudio::INT16, true, 0.0, NULL); + + if (inputParameters.numChannels() > 0) + { + std::cout << "Supported standard sample rates" << std::endl; + std::cout << " for half-duplex 16 bit " << inputParameters.numChannels() << " channel input = " << std::endl; + printSupportedStandardSampleRates(inputParameters, portaudio::DirectionSpecificStreamParameters::null()); + } + + if (outputParameters.numChannels() > 0) + { + std::cout << "Supported standard sample rates" << std::endl; + std::cout << " for half-duplex 16 bit " << outputParameters.numChannels() << " channel output = " << std::endl; + printSupportedStandardSampleRates(portaudio::DirectionSpecificStreamParameters::null(), outputParameters); + } + + if (inputParameters.numChannels() > 0 && outputParameters.numChannels() > 0) + { + std::cout << "Supported standard sample rates" << std::endl; + std::cout << " for full-duplex 16 bit " << inputParameters.numChannels() << " channel input, " << outputParameters.numChannels() << " channel output = " << std::endl; + printSupportedStandardSampleRates(inputParameters, outputParameters); + } + } + + std::cout << "----------------------------------------------" << std::endl; + } + catch (const portaudio::PaException &e) + { + std::cout << "A PortAudio error occurred: " << e.paErrorText() << std::endl; + } + catch (const portaudio::PaCppException &e) + { + std::cout << "A PortAudioCpp error occurred: " << e.what() << std::endl; + } + catch (const std::exception &e) + { + std::cout << "A generic exception occurred: " << e.what() << std::endl; + } + catch (...) + { + std::cout << "An unknown exception occurred." << std::endl; + } + + return 0; } diff --git a/3rdparty/portaudio/bindings/cpp/example/sine.cxx b/3rdparty/portaudio/bindings/cpp/example/sine.cxx index 0676e3e76ca..acd01e613b1 100644 --- a/3rdparty/portaudio/bindings/cpp/example/sine.cxx +++ b/3rdparty/portaudio/bindings/cpp/example/sine.cxx @@ -20,50 +20,50 @@ const int TABLE_SIZE = 200; class SineGenerator { public: - SineGenerator(int tableSize) : tableSize_(tableSize), leftPhase_(0), rightPhase_(0) - { - const double PI = 3.14159265; - table_ = new float[tableSize]; - for (int i = 0; i < tableSize; ++i) - { - table_[i] = 0.125f * (float)sin(((double)i/(double)tableSize)*PI*2.); - } - } - - ~SineGenerator() - { - delete[] table_; - } - - int generate(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags) - { - assert(outputBuffer != NULL); - - float **out = static_cast(outputBuffer); - - for (unsigned int i = 0; i < framesPerBuffer; ++i) - { - out[0][i] = table_[leftPhase_]; - out[1][i] = table_[rightPhase_]; - - leftPhase_ += 1; - if (leftPhase_ >= tableSize_) - leftPhase_ -= tableSize_; - - rightPhase_ += 3; - if (rightPhase_ >= tableSize_) - rightPhase_ -= tableSize_; - } - - return paContinue; - } + SineGenerator(int tableSize) : tableSize_(tableSize), leftPhase_(0), rightPhase_(0) + { + const double PI = 3.14159265; + table_ = new float[tableSize]; + for (int i = 0; i < tableSize; ++i) + { + table_[i] = 0.125f * (float)sin(((double)i/(double)tableSize)*PI*2.); + } + } + + ~SineGenerator() + { + delete[] table_; + } + + int generate(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, + const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags) + { + assert(outputBuffer != NULL); + + float **out = static_cast(outputBuffer); + + for (unsigned int i = 0; i < framesPerBuffer; ++i) + { + out[0][i] = table_[leftPhase_]; + out[1][i] = table_[rightPhase_]; + + leftPhase_ += 1; + if (leftPhase_ >= tableSize_) + leftPhase_ -= tableSize_; + + rightPhase_ += 3; + if (rightPhase_ >= tableSize_) + rightPhase_ -= tableSize_; + } + + return paContinue; + } private: - float *table_; - int tableSize_; - int leftPhase_; - int rightPhase_; + float *table_; + int tableSize_; + int leftPhase_; + int rightPhase_; }; // --------------------------------------------------------------------------------------- @@ -72,66 +72,64 @@ private: int main(int, char *[]); int main(int, char *[]) { - try - { - // Create a SineGenerator object: - SineGenerator sineGenerator(TABLE_SIZE); - - std::cout << "Setting up PortAudio..." << std::endl; - - // Set up the System: - portaudio::AutoSystem autoSys; - portaudio::System &sys = portaudio::System::instance(); - - // Set up the parameters required to open a (Callback)Stream: - portaudio::DirectionSpecificStreamParameters outParams(sys.defaultOutputDevice(), 2, portaudio::FLOAT32, false, sys.defaultOutputDevice().defaultLowOutputLatency(), NULL); - portaudio::StreamParameters params(portaudio::DirectionSpecificStreamParameters::null(), outParams, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff); - - std::cout << "Opening stereo output stream..." << std::endl; - - // Create (and open) a new Stream, using the SineGenerator::generate function as a callback: - portaudio::MemFunCallbackStream stream(params, sineGenerator, &SineGenerator::generate); - - std::cout << "Starting playback for " << NUM_SECONDS << " seconds." << std::endl; - - // Start the Stream (audio playback starts): - stream.start(); - - // Wait for 5 seconds: - sys.sleep(NUM_SECONDS * 1000); - - std::cout << "Closing stream..." < stream(params, sineGenerator, &SineGenerator::generate); + + std::cout << "Starting playback for " << NUM_SECONDS << " seconds." << std::endl; + + // Start the Stream (audio playback starts): + stream.start(); + + // Wait for 5 seconds: + sys.sleep(NUM_SECONDS * 1000); + + std::cout << "Closing stream..." < stream = MemFunCallbackStream(parameters, *this, &MyClass::myCallbackFunction); @endverbatim - ////// - template - class MemFunCallbackStream : public CallbackStream - { - public: - typedef int (T::*CallbackFunPtr)(const void *, void *, unsigned long, const PaStreamCallbackTimeInfo *, - PaStreamCallbackFlags); - - // ------------------------------------------------------------------------------- - - MemFunCallbackStream() - { - } - - MemFunCallbackStream(const StreamParameters ¶meters, T &instance, CallbackFunPtr memFun) : adapter_(instance, memFun) - { - open(parameters); - } - - ~MemFunCallbackStream() - { - close(); - } - - void open(const StreamParameters ¶meters, T &instance, CallbackFunPtr memFun) - { - // XXX: need to check if already open? - - adapter_.init(instance, memFun); - open(parameters); - } - - private: - MemFunCallbackStream(const MemFunCallbackStream &); // non-copyable - MemFunCallbackStream &operator=(const MemFunCallbackStream &); // non-copyable - - ////// - /// @brief Inner class which adapts a member function callback to a CallbackInterface compliant - /// class (so it can be adapted using the paCallbackAdapter function). - ////// - class MemFunToCallbackInterfaceAdapter : public CallbackInterface - { - public: - MemFunToCallbackInterfaceAdapter() {} - MemFunToCallbackInterfaceAdapter(T &instance, CallbackFunPtr memFun) : instance_(&instance), memFun_(memFun) {} - - void init(T &instance, CallbackFunPtr memFun) - { - instance_ = &instance; - memFun_ = memFun; - } - - int paCallbackFun(const void *inputBuffer, void *outputBuffer, unsigned long numFrames, - const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags) - { - return (instance_->*memFun_)(inputBuffer, outputBuffer, numFrames, timeInfo, statusFlags); - } - - private: - T *instance_; - CallbackFunPtr memFun_; - }; - - MemFunToCallbackInterfaceAdapter adapter_; - - void open(const StreamParameters ¶meters) - { - PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), - parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), &impl::callbackInterfaceToPaCallbackAdapter, - static_cast(&adapter_)); - - if (err != paNoError) - throw PaException(err); - } - }; + ////// + /// @brief Callback stream using a class's member function as a callback. Template argument T is the type of the + /// class of which a member function is going to be used. + /// + /// Example usage: + /// @verbatim MemFunCallback stream = MemFunCallbackStream(parameters, *this, &MyClass::myCallbackFunction); @endverbatim + ////// + template + class MemFunCallbackStream : public CallbackStream + { + public: + typedef int (T::*CallbackFunPtr)(const void *, void *, unsigned long, const PaStreamCallbackTimeInfo *, + PaStreamCallbackFlags); + + // ------------------------------------------------------------------------------- + + MemFunCallbackStream() + { + } + + MemFunCallbackStream(const StreamParameters ¶meters, T &instance, CallbackFunPtr memFun) : adapter_(instance, memFun) + { + open(parameters); + } + + ~MemFunCallbackStream() + { + close(); + } + + void open(const StreamParameters ¶meters, T &instance, CallbackFunPtr memFun) + { + // XXX: need to check if already open? + + adapter_.init(instance, memFun); + open(parameters); + } + + private: + MemFunCallbackStream(const MemFunCallbackStream &); // non-copyable + MemFunCallbackStream &operator=(const MemFunCallbackStream &); // non-copyable + + ////// + /// @brief Inner class which adapts a member function callback to a CallbackInterface compliant + /// class (so it can be adapted using the paCallbackAdapter function). + ////// + class MemFunToCallbackInterfaceAdapter : public CallbackInterface + { + public: + MemFunToCallbackInterfaceAdapter() {} + MemFunToCallbackInterfaceAdapter(T &instance, CallbackFunPtr memFun) : instance_(&instance), memFun_(memFun) {} + + void init(T &instance, CallbackFunPtr memFun) + { + instance_ = &instance; + memFun_ = memFun; + } + + int paCallbackFun(const void *inputBuffer, void *outputBuffer, unsigned long numFrames, + const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags) + { + return (instance_->*memFun_)(inputBuffer, outputBuffer, numFrames, timeInfo, statusFlags); + } + + private: + T *instance_; + CallbackFunPtr memFun_; + }; + + MemFunToCallbackInterfaceAdapter adapter_; + + void open(const StreamParameters ¶meters) + { + PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), + parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), &impl::callbackInterfaceToPaCallbackAdapter, + static_cast(&adapter_)); + + if (err != paNoError) + throw PaException(err); + } + }; } // portaudio diff --git a/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/PortAudioCpp.hxx b/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/PortAudioCpp.hxx index 96df96e7248..2c4df8f068f 100644 --- a/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/PortAudioCpp.hxx +++ b/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/PortAudioCpp.hxx @@ -6,23 +6,23 @@ ////// /// @mainpage PortAudioCpp /// -///

PortAudioCpp - A Native C++ Binding of PortAudio V19

+///

PortAudioCpp - A Native C++ Binding of PortAudio V19

///

PortAudio

///

-/// PortAudio is a portable and mature C API for accessing audio hardware. It offers both callback-based and blocking -/// style input and output, deals with sample data format conversions, dithering and much more. There are a large number -/// of implementations available for various platforms including Windows MME, Windows DirectX, Windows and MacOS (Classic) -/// ASIO, MacOS Classic SoundManager, MacOS X CoreAudio, OSS (Linux), Linux ALSA, JACK (MacOS X and Linux) and SGI Irix -/// AL. Note that, currently not all of these implementations are equally complete or up-to-date (as PortAudio V19 is -/// still in development). Because PortAudio has a C API, it can easily be called from a variety of other programming +/// PortAudio is a portable and mature C API for accessing audio hardware. It offers both callback-based and blocking +/// style input and output, deals with sample data format conversions, dithering and much more. There are a large number +/// of implementations available for various platforms including Windows MME, Windows DirectX, Windows and MacOS (Classic) +/// ASIO, MacOS Classic SoundManager, MacOS X CoreAudio, OSS (Linux), Linux ALSA, JACK (MacOS X and Linux) and SGI Irix +/// AL. Note that, currently not all of these implementations are equally complete or up-to-date (as PortAudio V19 is +/// still in development). Because PortAudio has a C API, it can easily be called from a variety of other programming /// languages. ///

///

PortAudioCpp

///

-/// Although, it is possible to use PortAudio's C API from within a C++ program, this is usually a little awkward -/// as procedural and object-oriented paradigms need to be mixed. PortAudioCpp aims to resolve this by encapsulating -/// PortAudio's C API to form an equivalent object-oriented C++ API. It provides a more natural integration of PortAudio -/// into C++ programs as well as a more structured interface. PortAudio's concepts were preserved as much as possible and +/// Although, it is possible to use PortAudio's C API from within a C++ program, this is usually a little awkward +/// as procedural and object-oriented paradigms need to be mixed. PortAudioCpp aims to resolve this by encapsulating +/// PortAudio's C API to form an equivalent object-oriented C++ API. It provides a more natural integration of PortAudio +/// into C++ programs as well as a more structured interface. PortAudio's concepts were preserved as much as possible and /// no additional features were added except for some `convenience methods'. ///

///

@@ -30,15 +30,15 @@ ///

    ///
  • Structured object model.
  • ///
  • C++ exception handling instead of C-style error return codes.
  • -///
  • Handling of callbacks using free functions (C and C++), static functions, member functions or instances of classes +///
  • Handling of callbacks using free functions (C and C++), static functions, member functions or instances of classes /// derived from a given interface.
  • ///
  • STL compliant iterators to host APIs and devices.
  • ///
  • Some additional convenience functions to more easily set up and use PortAudio.
  • ///
///

///

-/// PortAudioCpp requires a recent version of the PortAudio V19 source code. This can be obtained from CVS or as a snapshot -/// from the website. The examples also require the ASIO 2 SDK which can be obtained from the Steinberg website. Alternatively, the +/// PortAudioCpp requires a recent version of the PortAudio V19 source code. This can be obtained from CVS or as a snapshot +/// from the website. The examples also require the ASIO 2 SDK which can be obtained from the Steinberg website. Alternatively, the /// examples can easily be modified to compile without needing ASIO. ///

///

@@ -50,12 +50,12 @@ /// Other platforms should be easily supported as PortAudioCpp is platform-independent and (reasonably) C++ standard compliant. ///

///

-/// This documentation mainly provides information specific to PortAudioCpp. For a more complete explaination of all of the +/// This documentation mainly provides information specific to PortAudioCpp. For a more complete explanation of all of the /// concepts used, please consult the PortAudio documentation. ///

///

-/// PortAudioCpp was developed by Merlijn Blaauw with many great suggestions and help from Ross Bencina. Ludwig Schwardt provided -/// GNU/Linux build files and checked G++ compatibility. PortAudioCpp may be used under the same licensing, conditions and +/// PortAudioCpp was developed by Merlijn Blaauw with many great suggestions and help from Ross Bencina. Ludwig Schwardt provided +/// GNU/Linux build files and checked G++ compatibility. PortAudioCpp may be used under the same licensing, conditions and /// warranty as PortAudio. See the PortAudio license for more details. ///

///

Links

@@ -69,8 +69,8 @@ ////// /// @namespace portaudio /// -/// To avoid name collision, everything in PortAudioCpp is in the portaudio -/// namespace. If this name is too long it's usually pretty safe to use an +/// To avoid name collision, everything in PortAudioCpp is in the portaudio +/// namespace. If this name is too long it's usually pretty safe to use an /// alias like ``namespace pa = portaudio;''. ////// diff --git a/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/SampleDataFormat.hxx b/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/SampleDataFormat.hxx index 1d3a1d9ea6c..a15d367adc6 100644 --- a/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/SampleDataFormat.hxx +++ b/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/SampleDataFormat.hxx @@ -11,21 +11,21 @@ namespace portaudio { - ////// - /// @brief PortAudio sample data formats. - /// - /// Small helper enum to wrap the PortAudio defines. - ////// - enum SampleDataFormat - { - INVALID_FORMAT = 0, - FLOAT32 = paFloat32, - INT32 = paInt32, - INT24 = paInt24, - INT16 = paInt16, - INT8 = paInt8, - UINT8 = paUInt8 - }; + ////// + /// @brief PortAudio sample data formats. + /// + /// Small helper enum to wrap the PortAudio defines. + ////// + enum SampleDataFormat + { + INVALID_FORMAT = 0, + FLOAT32 = paFloat32, + INT32 = paInt32, + INT24 = paInt24, + INT16 = paInt16, + INT8 = paInt8, + UINT8 = paUInt8 + }; } // namespace portaudio diff --git a/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/Stream.hxx b/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/Stream.hxx index 1aed747e5f6..2725ba7499b 100644 --- a/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/Stream.hxx +++ b/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/Stream.hxx @@ -8,7 +8,7 @@ // Forward declaration(s): namespace portaudio { - class StreamParameters; + class StreamParameters; } // --------------------------------------------------------------------------------------- @@ -18,65 +18,64 @@ namespace portaudio { - ////// - /// @brief A Stream represents an active or inactive input and/or output data - /// stream in the System. - /// - /// Concrete Stream classes should ensure themselves being in a closed state at - /// destruction (i.e. by calling their own close() method in their deconstructor). - /// Following good C++ programming practices, care must be taken to ensure no - /// exceptions are thrown by the deconstructor of these classes. As a consequence, - /// clients need to explicitly call close() to ensure the stream closed successfully. - /// - /// The Stream object can be used to manipulate the Stream's state. Also, time-constant - /// and time-varying information about the Stream can be retreived. - ////// - class Stream - { - public: - // Opening/closing: - virtual ~Stream(); + ////// + /// @brief A Stream represents an active or inactive input and/or output data + /// stream in the System. + /// + /// Concrete Stream classes should ensure themselves being in a closed state at + /// destruction (i.e. by calling their own close() method in their deconstructor). + /// Following good C++ programming practices, care must be taken to ensure no + /// exceptions are thrown by the deconstructor of these classes. As a consequence, + /// clients need to explicitly call close() to ensure the stream closed successfully. + /// + /// The Stream object can be used to manipulate the Stream's state. Also, time-constant + /// and time-varying information about the Stream can be retrieved. + ////// + class Stream + { + public: + // Opening/closing: + virtual ~Stream(); - virtual void close(); - bool isOpen() const; + virtual void close(); + bool isOpen() const; - // Additional set up: - void setStreamFinishedCallback(PaStreamFinishedCallback *callback); + // Additional set up: + void setStreamFinishedCallback(PaStreamFinishedCallback *callback); - // State management: - void start(); - void stop(); - void abort(); + // State management: + void start(); + void stop(); + void abort(); - bool isStopped() const; - bool isActive() const; + bool isStopped() const; + bool isActive() const; - // Stream info (time-constant, but might become time-variant soon): - PaTime inputLatency() const; - PaTime outputLatency() const; - double sampleRate() const; + // Stream info (time-constant, but might become time-variant soon): + PaTime inputLatency() const; + PaTime outputLatency() const; + double sampleRate() const; - // Stream info (time-varying): - PaTime time() const; + // Stream info (time-varying): + PaTime time() const; - // Accessors for PortAudio PaStream, useful for interfacing - // with PortAudio add-ons (such as PortMixer) for instance: - const PaStream *paStream() const; - PaStream *paStream(); + // Accessors for PortAudio PaStream, useful for interfacing + // with PortAudio add-ons (such as PortMixer) for instance: + const PaStream *paStream() const; + PaStream *paStream(); - protected: - Stream(); // abstract class + protected: + Stream(); // abstract class - PaStream *stream_; + PaStream *stream_; - private: - Stream(const Stream &); // non-copyable - Stream &operator=(const Stream &); // non-copyable - }; + private: + Stream(const Stream &); // non-copyable + Stream &operator=(const Stream &); // non-copyable + }; } // namespace portaudio #endif // INCLUDED_PORTAUDIO_STREAM_HXX - diff --git a/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/StreamParameters.hxx b/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/StreamParameters.hxx index c0ec9a9aeb0..32f5f21a22e 100644 --- a/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/StreamParameters.hxx +++ b/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/StreamParameters.hxx @@ -13,61 +13,61 @@ namespace portaudio { - ////// - /// @brief The entire set of parameters needed to configure and open - /// a Stream. - /// - /// It contains parameters of input, output and shared parameters. - /// Using the isSupported() method, the StreamParameters can be - /// checked if opening a Stream using this StreamParameters would - /// succeed or not. Accessors are provided to higher-level parameters - /// aswell as the lower-level parameters which are mainly intended for - /// internal use. - ////// - class StreamParameters - { - public: - StreamParameters(); - StreamParameters(const DirectionSpecificStreamParameters &inputParameters, - const DirectionSpecificStreamParameters &outputParameters, double sampleRate, - unsigned long framesPerBuffer, PaStreamFlags flags); - - // Set up for direction-specific: - void setInputParameters(const DirectionSpecificStreamParameters ¶meters); - void setOutputParameters(const DirectionSpecificStreamParameters ¶meters); - - // Set up for common parameters: - void setSampleRate(double sampleRate); - void setFramesPerBuffer(unsigned long framesPerBuffer); - void setFlag(PaStreamFlags flag); - void unsetFlag(PaStreamFlags flag); - void clearFlags(); - - // Validation: - bool isSupported() const; - - // Accessors (direction-specific): - DirectionSpecificStreamParameters &inputParameters(); - const DirectionSpecificStreamParameters &inputParameters() const; - DirectionSpecificStreamParameters &outputParameters(); - const DirectionSpecificStreamParameters &outputParameters() const; - - // Accessors (common): - double sampleRate() const; - unsigned long framesPerBuffer() const; - PaStreamFlags flags() const; - bool isFlagSet(PaStreamFlags flag) const; - - private: - // Half-duplex specific parameters: - DirectionSpecificStreamParameters inputParameters_; - DirectionSpecificStreamParameters outputParameters_; - - // Common parameters: - double sampleRate_; - unsigned long framesPerBuffer_; - PaStreamFlags flags_; - }; + ////// + /// @brief The entire set of parameters needed to configure and open + /// a Stream. + /// + /// It contains parameters of input, output and shared parameters. + /// Using the isSupported() method, the StreamParameters can be + /// checked if opening a Stream using this StreamParameters would + /// succeed or not. Accessors are provided to higher-level parameters + /// aswell as the lower-level parameters which are mainly intended for + /// internal use. + ////// + class StreamParameters + { + public: + StreamParameters(); + StreamParameters(const DirectionSpecificStreamParameters &inputParameters, + const DirectionSpecificStreamParameters &outputParameters, double sampleRate, + unsigned long framesPerBuffer, PaStreamFlags flags); + + // Set up for direction-specific: + void setInputParameters(const DirectionSpecificStreamParameters ¶meters); + void setOutputParameters(const DirectionSpecificStreamParameters ¶meters); + + // Set up for common parameters: + void setSampleRate(double sampleRate); + void setFramesPerBuffer(unsigned long framesPerBuffer); + void setFlag(PaStreamFlags flag); + void unsetFlag(PaStreamFlags flag); + void clearFlags(); + + // Validation: + bool isSupported() const; + + // Accessors (direction-specific): + DirectionSpecificStreamParameters &inputParameters(); + const DirectionSpecificStreamParameters &inputParameters() const; + DirectionSpecificStreamParameters &outputParameters(); + const DirectionSpecificStreamParameters &outputParameters() const; + + // Accessors (common): + double sampleRate() const; + unsigned long framesPerBuffer() const; + PaStreamFlags flags() const; + bool isFlagSet(PaStreamFlags flag) const; + + private: + // Half-duplex specific parameters: + DirectionSpecificStreamParameters inputParameters_; + DirectionSpecificStreamParameters outputParameters_; + + // Common parameters: + double sampleRate_; + unsigned long framesPerBuffer_; + PaStreamFlags flags_; + }; } // namespace portaudio diff --git a/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/System.hxx b/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/System.hxx index d5ff9dd2b3c..bdd966ebfa2 100644 --- a/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/System.hxx +++ b/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/System.hxx @@ -10,9 +10,9 @@ // Forward declaration(s): namespace portaudio { - class Device; - class Stream; - class HostApi; + class Device; + class Stream; + class HostApi; } // --------------------------------------------------------------------------------------- @@ -22,86 +22,85 @@ namespace portaudio { - ////// - /// @brief System singleton which represents the PortAudio system. - /// - /// The System is used to initialize/terminate PortAudio and provide - /// a single acccess point to the PortAudio System (instance()). - /// It can be used to iterate through all HostApi 's in the System as - /// well as all devices in the System. It also provides some utility - /// functionality of PortAudio. - /// - /// Terminating the System will also abort and close the open streams. - /// The Stream objects will need to be deallocated by the client though - /// (it's usually a good idea to have them cleaned up automatically). - ////// - class System - { - public: - class HostApiIterator; // forward declaration - class DeviceIterator; // forward declaration + ////// + /// @brief System singleton which represents the PortAudio system. + /// + /// The System is used to initialize/terminate PortAudio and provide + /// a single access point to the PortAudio System (instance()). + /// It can be used to iterate through all HostApi 's in the System as + /// well as all devices in the System. It also provides some utility + /// functionality of PortAudio. + /// + /// Terminating the System will also abort and close the open streams. + /// The Stream objects will need to be deallocated by the client though + /// (it's usually a good idea to have them cleaned up automatically). + ////// + class System + { + public: + class HostApiIterator; // forward declaration + class DeviceIterator; // forward declaration - // ------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- - static int version(); - static const char *versionText(); + static int version(); + static const char *versionText(); - static void initialize(); - static void terminate(); + static void initialize(); + static void terminate(); - static System &instance(); - static bool exists(); + static System &instance(); + static bool exists(); - // ------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- - // host apis: - HostApiIterator hostApisBegin(); - HostApiIterator hostApisEnd(); + // host apis: + HostApiIterator hostApisBegin(); + HostApiIterator hostApisEnd(); - HostApi &defaultHostApi(); + HostApi &defaultHostApi(); - HostApi &hostApiByTypeId(PaHostApiTypeId type); - HostApi &hostApiByIndex(PaHostApiIndex index); + HostApi &hostApiByTypeId(PaHostApiTypeId type); + HostApi &hostApiByIndex(PaHostApiIndex index); - int hostApiCount(); + int hostApiCount(); - // ------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- - // devices: - DeviceIterator devicesBegin(); - DeviceIterator devicesEnd(); + // devices: + DeviceIterator devicesBegin(); + DeviceIterator devicesEnd(); - Device &defaultInputDevice(); - Device &defaultOutputDevice(); + Device &defaultInputDevice(); + Device &defaultOutputDevice(); - Device &deviceByIndex(PaDeviceIndex index); + Device &deviceByIndex(PaDeviceIndex index); - int deviceCount(); + int deviceCount(); - static Device &nullDevice(); + static Device &nullDevice(); - // ------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- - // misc: - void sleep(long msec); - int sizeOfSample(PaSampleFormat format); + // misc: + void sleep(long msec); + int sizeOfSample(PaSampleFormat format); - private: - System(); - ~System(); + private: + System(); + ~System(); - static System *instance_; - static int initCount_; + static System *instance_; + static int initCount_; - static HostApi **hostApis_; - static Device **devices_; + static HostApi **hostApis_; + static Device **devices_; - static Device *nullDevice_; - }; + static Device *nullDevice_; + }; } // namespace portaudio #endif // INCLUDED_PORTAUDIO_SYSTEM_HXX - diff --git a/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/SystemDeviceIterator.hxx b/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/SystemDeviceIterator.hxx index ffa195d2872..d5ae31eba34 100644 --- a/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/SystemDeviceIterator.hxx +++ b/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/SystemDeviceIterator.hxx @@ -13,8 +13,8 @@ // Forward declaration(s): namespace portaudio { - class Device; - class HostApi; + class Device; + class HostApi; } // --------------------------------------------------------------------------------------- @@ -23,39 +23,39 @@ namespace portaudio namespace portaudio { - - ////// - /// @brief Iterator class for iterating through all Devices in a System. - /// - /// Devices will be iterated by iterating all Devices in each - /// HostApi in the System. Compliant with the STL bidirectional - /// iterator concept. - ////// - class System::DeviceIterator - { - public: - typedef std::bidirectional_iterator_tag iterator_category; - typedef Device value_type; - typedef ptrdiff_t difference_type; - typedef Device * pointer; - typedef Device & reference; - - Device &operator*() const; - Device *operator->() const; - - DeviceIterator &operator++(); - DeviceIterator operator++(int); - DeviceIterator &operator--(); - DeviceIterator operator--(int); - - bool operator==(const DeviceIterator &rhs) const; - bool operator!=(const DeviceIterator &rhs) const; - - private: - friend class System; - friend class HostApi; - Device **ptr_; - }; + + ////// + /// @brief Iterator class for iterating through all Devices in a System. + /// + /// Devices will be iterated by iterating all Devices in each + /// HostApi in the System. Compliant with the STL bidirectional + /// iterator concept. + ////// + class System::DeviceIterator + { + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef Device value_type; + typedef ptrdiff_t difference_type; + typedef Device * pointer; + typedef Device & reference; + + Device &operator*() const; + Device *operator->() const; + + DeviceIterator &operator++(); + DeviceIterator operator++(int); + DeviceIterator &operator--(); + DeviceIterator operator--(int); + + bool operator==(const DeviceIterator &rhs) const; + bool operator!=(const DeviceIterator &rhs) const; + + private: + friend class System; + friend class HostApi; + Device **ptr_; + }; } // namespace portaudio @@ -63,4 +63,3 @@ namespace portaudio // --------------------------------------------------------------------------------------- #endif // INCLUDED_PORTAUDIO_SYSTEMDEVICEITERATOR_HXX - diff --git a/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/SystemHostApiIterator.hxx b/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/SystemHostApiIterator.hxx index 3e6a978a326..a3e2f4b3c23 100644 --- a/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/SystemHostApiIterator.hxx +++ b/3rdparty/portaudio/bindings/cpp/include/portaudiocpp/SystemHostApiIterator.hxx @@ -13,7 +13,7 @@ // Forward declaration(s): namespace portaudio { - class HostApi; + class HostApi; } // --------------------------------------------------------------------------------------- @@ -23,35 +23,35 @@ namespace portaudio { - ////// - /// @brief Iterator class for iterating through all HostApis in a System. - /// - /// Compliant with the STL bidirectional iterator concept. - ////// - class System::HostApiIterator - { - public: - typedef std::bidirectional_iterator_tag iterator_category; - typedef Device value_type; - typedef ptrdiff_t difference_type; - typedef HostApi * pointer; - typedef HostApi & reference; - - HostApi &operator*() const; - HostApi *operator->() const; - - HostApiIterator &operator++(); - HostApiIterator operator++(int); - HostApiIterator &operator--(); - HostApiIterator operator--(int); - - bool operator==(const HostApiIterator &rhs) const; - bool operator!=(const HostApiIterator &rhs) const; - - private: - friend class System; - HostApi **ptr_; - }; + ////// + /// @brief Iterator class for iterating through all HostApis in a System. + /// + /// Compliant with the STL bidirectional iterator concept. + ////// + class System::HostApiIterator + { + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef Device value_type; + typedef ptrdiff_t difference_type; + typedef HostApi * pointer; + typedef HostApi & reference; + + HostApi &operator*() const; + HostApi *operator->() const; + + HostApiIterator &operator++(); + HostApiIterator operator++(int); + HostApiIterator &operator--(); + HostApiIterator operator--(int); + + bool operator==(const HostApiIterator &rhs) const; + bool operator!=(const HostApiIterator &rhs) const; + + private: + friend class System; + HostApi **ptr_; + }; } // namespace portaudio diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/AsioDeviceAdapter.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/AsioDeviceAdapter.cxx index 3efc100f62f..e7fd1ee5fa9 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/AsioDeviceAdapter.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/AsioDeviceAdapter.cxx @@ -9,75 +9,73 @@ namespace portaudio { - AsioDeviceAdapter::AsioDeviceAdapter(Device &device) - { - if (device.hostApi().typeId() != paASIO) - throw PaCppException(PaCppException::UNABLE_TO_ADAPT_DEVICE); + AsioDeviceAdapter::AsioDeviceAdapter(Device &device) + { + if (device.hostApi().typeId() != paASIO) + throw PaCppException(PaCppException::UNABLE_TO_ADAPT_DEVICE); - device_ = &device; + device_ = &device; - PaError err = PaAsio_GetAvailableLatencyValues(device_->index(), &minBufferSize_, &maxBufferSize_, - &preferredBufferSize_, &granularity_); + PaError err = PaAsio_GetAvailableLatencyValues(device_->index(), &minBufferSize_, &maxBufferSize_, + &preferredBufferSize_, &granularity_); - if (err != paNoError) - throw PaException(err); + if (err != paNoError) + throw PaException(err); - } + } - Device &AsioDeviceAdapter::device() - { - return *device_; - } + Device &AsioDeviceAdapter::device() + { + return *device_; + } - long AsioDeviceAdapter::minBufferSize() const - { - return minBufferSize_; - } + long AsioDeviceAdapter::minBufferSize() const + { + return minBufferSize_; + } - long AsioDeviceAdapter::maxBufferSize() const - { - return maxBufferSize_; - } + long AsioDeviceAdapter::maxBufferSize() const + { + return maxBufferSize_; + } - long AsioDeviceAdapter::preferredBufferSize() const - { - return preferredBufferSize_; - } + long AsioDeviceAdapter::preferredBufferSize() const + { + return preferredBufferSize_; + } - long AsioDeviceAdapter::granularity() const - { - return granularity_; - } + long AsioDeviceAdapter::granularity() const + { + return granularity_; + } - void AsioDeviceAdapter::showControlPanel(void *systemSpecific) - { - PaError err = PaAsio_ShowControlPanel(device_->index(), systemSpecific); + void AsioDeviceAdapter::showControlPanel(void *systemSpecific) + { + PaError err = PaAsio_ShowControlPanel(device_->index(), systemSpecific); - if (err != paNoError) - throw PaException(err); - } + if (err != paNoError) + throw PaException(err); + } - const char *AsioDeviceAdapter::inputChannelName(int channelIndex) const - { - const char *channelName; - PaError err = PaAsio_GetInputChannelName(device_->index(), channelIndex, &channelName); + const char *AsioDeviceAdapter::inputChannelName(int channelIndex) const + { + const char *channelName; + PaError err = PaAsio_GetInputChannelName(device_->index(), channelIndex, &channelName); - if (err != paNoError) - throw PaException(err); + if (err != paNoError) + throw PaException(err); - return channelName; - } + return channelName; + } - const char *AsioDeviceAdapter::outputChannelName(int channelIndex) const - { - const char *channelName; - PaError err = PaAsio_GetOutputChannelName(device_->index(), channelIndex, &channelName); + const char *AsioDeviceAdapter::outputChannelName(int channelIndex) const + { + const char *channelName; + PaError err = PaAsio_GetOutputChannelName(device_->index(), channelIndex, &channelName); - if (err != paNoError) - throw PaException(err); + if (err != paNoError) + throw PaException(err); - return channelName; - } + return channelName; + } } - - diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/BlockingStream.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/BlockingStream.cxx index b26b9e81a4f..751e1f21b7e 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/BlockingStream.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/BlockingStream.cxx @@ -8,93 +8,90 @@ namespace portaudio { - // -------------------------------------------------------------------------------------- - - BlockingStream::BlockingStream() - { - } - - BlockingStream::BlockingStream(const StreamParameters ¶meters) - { - open(parameters); - } - - BlockingStream::~BlockingStream() - { - try - { - close(); - } - catch (...) - { - // ignore all errors - } - } - - // -------------------------------------------------------------------------------------- - - void BlockingStream::open(const StreamParameters ¶meters) - { - PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), - parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), NULL, NULL); - - if (err != paNoError) - { - throw PaException(err); - } - } - - // -------------------------------------------------------------------------------------- - - void BlockingStream::read(void *buffer, unsigned long numFrames) - { - PaError err = Pa_ReadStream(stream_, buffer, numFrames); - - if (err != paNoError) - { - throw PaException(err); - } - } - - void BlockingStream::write(const void *buffer, unsigned long numFrames) - { - PaError err = Pa_WriteStream(stream_, buffer, numFrames); - - if (err != paNoError) - { - throw PaException(err); - } - } - - // -------------------------------------------------------------------------------------- - - signed long BlockingStream::availableReadSize() const - { - signed long avail = Pa_GetStreamReadAvailable(stream_); - - if (avail < 0) - { - throw PaException(avail); - } - - return avail; - } - - signed long BlockingStream::availableWriteSize() const - { - signed long avail = Pa_GetStreamWriteAvailable(stream_); - - if (avail < 0) - { - throw PaException(avail); - } - - return avail; - } - - // -------------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------------- + + BlockingStream::BlockingStream() + { + } + + BlockingStream::BlockingStream(const StreamParameters ¶meters) + { + open(parameters); + } + + BlockingStream::~BlockingStream() + { + try + { + close(); + } + catch (...) + { + // ignore all errors + } + } + + // -------------------------------------------------------------------------------------- + + void BlockingStream::open(const StreamParameters ¶meters) + { + PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), + parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), NULL, NULL); + + if (err != paNoError) + { + throw PaException(err); + } + } + + // -------------------------------------------------------------------------------------- + + void BlockingStream::read(void *buffer, unsigned long numFrames) + { + PaError err = Pa_ReadStream(stream_, buffer, numFrames); + + if (err != paNoError) + { + throw PaException(err); + } + } + + void BlockingStream::write(const void *buffer, unsigned long numFrames) + { + PaError err = Pa_WriteStream(stream_, buffer, numFrames); + + if (err != paNoError) + { + throw PaException(err); + } + } + + // -------------------------------------------------------------------------------------- + + signed long BlockingStream::availableReadSize() const + { + signed long avail = Pa_GetStreamReadAvailable(stream_); + + if (avail < 0) + { + throw PaException(avail); + } + + return avail; + } + + signed long BlockingStream::availableWriteSize() const + { + signed long avail = Pa_GetStreamWriteAvailable(stream_); + + if (avail < 0) + { + throw PaException(avail); + } + + return avail; + } + + // -------------------------------------------------------------------------------------- } // portaudio - - - diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CFunCallbackStream.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CFunCallbackStream.cxx index 9cceda9ab9e..7dcc751d121 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CFunCallbackStream.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CFunCallbackStream.cxx @@ -5,37 +5,37 @@ namespace portaudio { - CFunCallbackStream::CFunCallbackStream() - { - } + CFunCallbackStream::CFunCallbackStream() + { + } - CFunCallbackStream::CFunCallbackStream(const StreamParameters ¶meters, PaStreamCallback *funPtr, void *userData) - { - open(parameters, funPtr, userData); - } + CFunCallbackStream::CFunCallbackStream(const StreamParameters ¶meters, PaStreamCallback *funPtr, void *userData) + { + open(parameters, funPtr, userData); + } - CFunCallbackStream::~CFunCallbackStream() - { - try - { - close(); - } - catch (...) - { - // ignore all errors - } - } + CFunCallbackStream::~CFunCallbackStream() + { + try + { + close(); + } + catch (...) + { + // ignore all errors + } + } - // ---------------------------------------------------------------------------------== + // ---------------------------------------------------------------------------------== - void CFunCallbackStream::open(const StreamParameters ¶meters, PaStreamCallback *funPtr, void *userData) - { - PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), - parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), funPtr, userData); + void CFunCallbackStream::open(const StreamParameters ¶meters, PaStreamCallback *funPtr, void *userData) + { + PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), + parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), funPtr, userData); - if (err != paNoError) - { - throw PaException(err); - } - } + if (err != paNoError) + { + throw PaException(err); + } + } } diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CallbackInterface.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CallbackInterface.cxx index 01372612e49..30ad933126e 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CallbackInterface.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CallbackInterface.cxx @@ -3,23 +3,21 @@ namespace portaudio { - namespace impl - { + namespace impl + { - ////// - /// Adapts any CallbackInterface object to a C-callable function (ie this function). A - /// pointer to the object should be passed as ``userData'' when setting up the callback. - ////// - int callbackInterfaceToPaCallbackAdapter(const void *inputBuffer, void *outputBuffer, unsigned long numFrames, - const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData) - { - CallbackInterface *cb = static_cast(userData); - return cb->paCallbackFun(inputBuffer, outputBuffer, numFrames, timeInfo, statusFlags); - } + ////// + /// Adapts any CallbackInterface object to a C-callable function (ie this function). A + /// pointer to the object should be passed as ``userData'' when setting up the callback. + ////// + int callbackInterfaceToPaCallbackAdapter(const void *inputBuffer, void *outputBuffer, unsigned long numFrames, + const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData) + { + CallbackInterface *cb = static_cast(userData); + return cb->paCallbackFun(inputBuffer, outputBuffer, numFrames, timeInfo, statusFlags); + } - } // namespace impl + } // namespace impl } // namespace portaudio - - diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CallbackStream.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CallbackStream.cxx index b6c8e1d03ee..d295a0a5ae0 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CallbackStream.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CallbackStream.cxx @@ -2,19 +2,19 @@ namespace portaudio { - CallbackStream::CallbackStream() - { - } + CallbackStream::CallbackStream() + { + } - CallbackStream::~CallbackStream() - { - } + CallbackStream::~CallbackStream() + { + } - // ----------------------------------------------------------------------------------- - - double CallbackStream::cpuLoad() const - { - return Pa_GetStreamCpuLoad(stream_); - } + // ----------------------------------------------------------------------------------- + + double CallbackStream::cpuLoad() const + { + return Pa_GetStreamCpuLoad(stream_); + } } // namespace portaudio diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CppFunCallbackStream.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CppFunCallbackStream.cxx index fe0b4ab0cd5..19a76ee6ee6 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CppFunCallbackStream.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/CppFunCallbackStream.cxx @@ -5,77 +5,77 @@ namespace portaudio { - namespace impl - { - ////// - /// Adapts any a C++ callback to a C-callable function (ie this function). A - /// pointer to a struct with the C++ function pointer and the actual user data should be - /// passed as the ``userData'' parameter when setting up the callback. - ////// - int cppCallbackToPaCallbackAdapter(const void *inputBuffer, void *outputBuffer, unsigned long numFrames, - const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData) - { - FunCallbackStream::CppToCCallbackData *data = static_cast(userData); - return data->funPtr(inputBuffer, outputBuffer, numFrames, timeInfo, statusFlags, data->userData); - } - } + namespace impl + { + ////// + /// Adapts any a C++ callback to a C-callable function (ie this function). A + /// pointer to a struct with the C++ function pointer and the actual user data should be + /// passed as the ``userData'' parameter when setting up the callback. + ////// + int cppCallbackToPaCallbackAdapter(const void *inputBuffer, void *outputBuffer, unsigned long numFrames, + const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData) + { + FunCallbackStream::CppToCCallbackData *data = static_cast(userData); + return data->funPtr(inputBuffer, outputBuffer, numFrames, timeInfo, statusFlags, data->userData); + } + } - // ----------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- - FunCallbackStream::CppToCCallbackData::CppToCCallbackData() - { - } + FunCallbackStream::CppToCCallbackData::CppToCCallbackData() + { + } - FunCallbackStream::CppToCCallbackData::CppToCCallbackData(CallbackFunPtr funPtr, void *userData) : funPtr(funPtr), userData(userData) - { - } + FunCallbackStream::CppToCCallbackData::CppToCCallbackData(CallbackFunPtr funPtr, void *userData) : funPtr(funPtr), userData(userData) + { + } - void FunCallbackStream::CppToCCallbackData::init(CallbackFunPtr funPtr, void *userData) - { - this->funPtr = funPtr; - this->userData = userData; - } + void FunCallbackStream::CppToCCallbackData::init(CallbackFunPtr funPtr, void *userData) + { + this->funPtr = funPtr; + this->userData = userData; + } - // ----------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- - FunCallbackStream::FunCallbackStream() - { - } + FunCallbackStream::FunCallbackStream() + { + } - FunCallbackStream::FunCallbackStream(const StreamParameters ¶meters, CallbackFunPtr funPtr, void *userData) : adapterData_(funPtr, userData) - { - open(parameters); - } + FunCallbackStream::FunCallbackStream(const StreamParameters ¶meters, CallbackFunPtr funPtr, void *userData) : adapterData_(funPtr, userData) + { + open(parameters); + } - FunCallbackStream::~FunCallbackStream() - { - try - { - close(); - } - catch (...) - { - // ignore all errors - } - } + FunCallbackStream::~FunCallbackStream() + { + try + { + close(); + } + catch (...) + { + // ignore all errors + } + } - void FunCallbackStream::open(const StreamParameters ¶meters, CallbackFunPtr funPtr, void *userData) - { - adapterData_.init(funPtr, userData); - open(parameters); - } + void FunCallbackStream::open(const StreamParameters ¶meters, CallbackFunPtr funPtr, void *userData) + { + adapterData_.init(funPtr, userData); + open(parameters); + } - void FunCallbackStream::open(const StreamParameters ¶meters) - { - PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), - parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), &impl::cppCallbackToPaCallbackAdapter, - static_cast(&adapterData_)); + void FunCallbackStream::open(const StreamParameters ¶meters) + { + PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), + parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), &impl::cppCallbackToPaCallbackAdapter, + static_cast(&adapterData_)); - if (err != paNoError) - { - throw PaException(err); - } - } + if (err != paNoError) + { + throw PaException(err); + } + } - // ----------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- } diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/Device.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/Device.cxx index 7b21b03ca52..727b7214480 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/Device.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/Device.cxx @@ -9,160 +9,158 @@ namespace portaudio { - // ------------------------------------------------------------------------------- - - Device::Device(PaDeviceIndex index) : index_(index) - { - if (index == paNoDevice) - info_ = NULL; - else - info_ = Pa_GetDeviceInfo(index); - } - - Device::~Device() - { - } - - PaDeviceIndex Device::index() const - { - return index_; - } - - const char *Device::name() const - { - if (info_ == NULL) - return ""; - - return info_->name; - } - - int Device::maxInputChannels() const - { - if (info_ == NULL) - return 0; - - return info_->maxInputChannels; - } - - int Device::maxOutputChannels() const - { - if (info_ == NULL) - return 0; - - return info_->maxOutputChannels; - } - - PaTime Device::defaultLowInputLatency() const - { - if (info_ == NULL) - return static_cast(0.0); - - return info_->defaultLowInputLatency; - } - - PaTime Device::defaultHighInputLatency() const - { - if (info_ == NULL) - return static_cast(0.0); - - return info_->defaultHighInputLatency; - } - - PaTime Device::defaultLowOutputLatency() const - { - if (info_ == NULL) - return static_cast(0.0); - - return info_->defaultLowOutputLatency; - } - - PaTime Device::defaultHighOutputLatency() const - { - if (info_ == NULL) - return static_cast(0.0); - - return info_->defaultHighOutputLatency; - } - - double Device::defaultSampleRate() const - { - if (info_ == NULL) - return 0.0; - - return info_->defaultSampleRate; - } - - // ------------------------------------------------------------------------------- - - bool Device::isInputOnlyDevice() const - { - return (maxOutputChannels() == 0); - } - - bool Device::isOutputOnlyDevice() const - { - return (maxInputChannels() == 0); - } - - bool Device::isFullDuplexDevice() const - { - return (maxInputChannels() > 0 && maxOutputChannels() > 0); - } - - bool Device::isSystemDefaultInputDevice() const - { - return (System::instance().defaultInputDevice() == *this); - } - - bool Device::isSystemDefaultOutputDevice() const - { - return (System::instance().defaultOutputDevice() == *this); - } + // ------------------------------------------------------------------------------- + + Device::Device(PaDeviceIndex index) : index_(index) + { + if (index == paNoDevice) + info_ = NULL; + else + info_ = Pa_GetDeviceInfo(index); + } + + Device::~Device() + { + } + + PaDeviceIndex Device::index() const + { + return index_; + } + + const char *Device::name() const + { + if (info_ == NULL) + return ""; + + return info_->name; + } + + int Device::maxInputChannels() const + { + if (info_ == NULL) + return 0; + + return info_->maxInputChannels; + } + + int Device::maxOutputChannels() const + { + if (info_ == NULL) + return 0; + + return info_->maxOutputChannels; + } + + PaTime Device::defaultLowInputLatency() const + { + if (info_ == NULL) + return static_cast(0.0); + + return info_->defaultLowInputLatency; + } + + PaTime Device::defaultHighInputLatency() const + { + if (info_ == NULL) + return static_cast(0.0); + + return info_->defaultHighInputLatency; + } + + PaTime Device::defaultLowOutputLatency() const + { + if (info_ == NULL) + return static_cast(0.0); + + return info_->defaultLowOutputLatency; + } + + PaTime Device::defaultHighOutputLatency() const + { + if (info_ == NULL) + return static_cast(0.0); + + return info_->defaultHighOutputLatency; + } + + double Device::defaultSampleRate() const + { + if (info_ == NULL) + return 0.0; + + return info_->defaultSampleRate; + } + + // ------------------------------------------------------------------------------- + + bool Device::isInputOnlyDevice() const + { + return (maxOutputChannels() == 0); + } + + bool Device::isOutputOnlyDevice() const + { + return (maxInputChannels() == 0); + } + + bool Device::isFullDuplexDevice() const + { + return (maxInputChannels() > 0 && maxOutputChannels() > 0); + } + + bool Device::isSystemDefaultInputDevice() const + { + return (System::instance().defaultInputDevice() == *this); + } + + bool Device::isSystemDefaultOutputDevice() const + { + return (System::instance().defaultOutputDevice() == *this); + } - bool Device::isHostApiDefaultInputDevice() const - { - return (hostApi().defaultInputDevice() == *this); - } - - bool Device::isHostApiDefaultOutputDevice() const - { - return (hostApi().defaultOutputDevice() == *this); - } + bool Device::isHostApiDefaultInputDevice() const + { + return (hostApi().defaultInputDevice() == *this); + } + + bool Device::isHostApiDefaultOutputDevice() const + { + return (hostApi().defaultOutputDevice() == *this); + } - // ------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- - bool Device::operator==(const Device &rhs) const - { - return (index_ == rhs.index_); - } + bool Device::operator==(const Device &rhs) const + { + return (index_ == rhs.index_); + } - bool Device::operator!=(const Device &rhs) const - { - return !(*this == rhs); - } + bool Device::operator!=(const Device &rhs) const + { + return !(*this == rhs); + } - // ------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- - HostApi &Device::hostApi() - { - // NOTE: will cause an exception when called for the null device - if (info_ == NULL) - throw PaException(paInternalError); + HostApi &Device::hostApi() + { + // NOTE: will cause an exception when called for the null device + if (info_ == NULL) + throw PaException(paInternalError); - return System::instance().hostApiByIndex(info_->hostApi); - } + return System::instance().hostApiByIndex(info_->hostApi); + } - const HostApi &Device::hostApi() const - { - // NOTE; will cause an exception when called for the null device - if (info_ == NULL) - throw PaException(paInternalError); + const HostApi &Device::hostApi() const + { + // NOTE; will cause an exception when called for the null device + if (info_ == NULL) + throw PaException(paInternalError); - return System::instance().hostApiByIndex(info_->hostApi); - } + return System::instance().hostApiByIndex(info_->hostApi); + } - // ------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------- } // namespace portaudio - - diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/DirectionSpecificStreamParameters.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/DirectionSpecificStreamParameters.cxx index 68453d02121..558f2e2bb92 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/DirectionSpecificStreamParameters.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/DirectionSpecificStreamParameters.cxx @@ -5,159 +5,159 @@ namespace portaudio { - // ----------------------------------------------------------------------------------- - - ////// - /// Returns a `nil' DirectionSpecificStreamParameters object. This can be used to - /// specify that one direction of a Stream is not required (i.e. when creating - /// a half-duplex Stream). All fields of the null DirectionSpecificStreamParameters - /// object are invalid except for the device and the number of channel, which are set - /// to paNoDevice and 0 respectively. - ////// - DirectionSpecificStreamParameters DirectionSpecificStreamParameters::null() - { - DirectionSpecificStreamParameters tmp; - tmp.paStreamParameters_.device = paNoDevice; - tmp.paStreamParameters_.channelCount = 0; - return tmp; - } - - // ----------------------------------------------------------------------------------- - - ////// - /// Default constructor -- all parameters will be uninitialized. - ////// - DirectionSpecificStreamParameters::DirectionSpecificStreamParameters() - { - } - - ////// - /// Constructor which sets all required fields. - ////// - DirectionSpecificStreamParameters::DirectionSpecificStreamParameters(const Device &device, int numChannels, - SampleDataFormat format, bool interleaved, PaTime suggestedLatency, void *hostApiSpecificStreamInfo) - { - setDevice(device); - setNumChannels(numChannels); - setSampleFormat(format, interleaved); - setSuggestedLatency(suggestedLatency); - setHostApiSpecificStreamInfo(hostApiSpecificStreamInfo); - } - - // ----------------------------------------------------------------------------------- - - void DirectionSpecificStreamParameters::setDevice(const Device &device) - { - paStreamParameters_.device = device.index(); - } - - void DirectionSpecificStreamParameters::setNumChannels(int numChannels) - { - paStreamParameters_.channelCount = numChannels; - } - - void DirectionSpecificStreamParameters::setSampleFormat(SampleDataFormat format, bool interleaved) - { - paStreamParameters_.sampleFormat = static_cast(format); - - if (!interleaved) - paStreamParameters_.sampleFormat |= paNonInterleaved; - } - - void DirectionSpecificStreamParameters::setHostApiSpecificSampleFormat(PaSampleFormat format, bool interleaved) - { - paStreamParameters_.sampleFormat = format; - - paStreamParameters_.sampleFormat |= paCustomFormat; - - if (!interleaved) - paStreamParameters_.sampleFormat |= paNonInterleaved; - } - - void DirectionSpecificStreamParameters::setSuggestedLatency(PaTime latency) - { - paStreamParameters_.suggestedLatency = latency; - } - - void DirectionSpecificStreamParameters::setHostApiSpecificStreamInfo(void *streamInfo) - { - paStreamParameters_.hostApiSpecificStreamInfo = streamInfo; - } - - // ----------------------------------------------------------------------------------- - - PaStreamParameters *DirectionSpecificStreamParameters::paStreamParameters() - { - if (paStreamParameters_.channelCount > 0 && paStreamParameters_.device != paNoDevice) - return &paStreamParameters_; - else - return NULL; - } - - const PaStreamParameters *DirectionSpecificStreamParameters::paStreamParameters() const - { - if (paStreamParameters_.channelCount > 0 && paStreamParameters_.device != paNoDevice) - return &paStreamParameters_; - else - return NULL; - } - - Device &DirectionSpecificStreamParameters::device() const - { - return System::instance().deviceByIndex(paStreamParameters_.device); - } - - int DirectionSpecificStreamParameters::numChannels() const - { - return paStreamParameters_.channelCount; - } - - ////// - /// Returns the (non host api-specific) sample format, without including - /// the paNonInterleaved flag. If the sample format is host api-spefific, - /// INVALID_FORMAT (0) will be returned. - ////// - SampleDataFormat DirectionSpecificStreamParameters::sampleFormat() const - { - if (isSampleFormatHostApiSpecific()) - return INVALID_FORMAT; - else - return static_cast(paStreamParameters_.sampleFormat & ~paNonInterleaved); - } - - bool DirectionSpecificStreamParameters::isSampleFormatInterleaved() const - { - return ((paStreamParameters_.sampleFormat & paNonInterleaved) == 0); - } - - bool DirectionSpecificStreamParameters::isSampleFormatHostApiSpecific() const - { - return ((paStreamParameters_.sampleFormat & paCustomFormat) == 0); - } - - ////// - /// Returns the host api-specific sample format, without including any - /// paCustomFormat or paNonInterleaved flags. Will return 0 if the sample format is - /// not host api-specific. - ////// - PaSampleFormat DirectionSpecificStreamParameters::hostApiSpecificSampleFormat() const - { - if (isSampleFormatHostApiSpecific()) - return paStreamParameters_.sampleFormat & ~paCustomFormat & ~paNonInterleaved; - else - return 0; - } - - PaTime DirectionSpecificStreamParameters::suggestedLatency() const - { - return paStreamParameters_.suggestedLatency; - } - - void *DirectionSpecificStreamParameters::hostApiSpecificStreamInfo() const - { - return paStreamParameters_.hostApiSpecificStreamInfo; - } - - // ----------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- + + ////// + /// Returns a `nil' DirectionSpecificStreamParameters object. This can be used to + /// specify that one direction of a Stream is not required (i.e. when creating + /// a half-duplex Stream). All fields of the null DirectionSpecificStreamParameters + /// object are invalid except for the device and the number of channel, which are set + /// to paNoDevice and 0 respectively. + ////// + DirectionSpecificStreamParameters DirectionSpecificStreamParameters::null() + { + DirectionSpecificStreamParameters tmp; + tmp.paStreamParameters_.device = paNoDevice; + tmp.paStreamParameters_.channelCount = 0; + return tmp; + } + + // ----------------------------------------------------------------------------------- + + ////// + /// Default constructor -- all parameters will be uninitialized. + ////// + DirectionSpecificStreamParameters::DirectionSpecificStreamParameters() + { + } + + ////// + /// Constructor which sets all required fields. + ////// + DirectionSpecificStreamParameters::DirectionSpecificStreamParameters(const Device &device, int numChannels, + SampleDataFormat format, bool interleaved, PaTime suggestedLatency, void *hostApiSpecificStreamInfo) + { + setDevice(device); + setNumChannels(numChannels); + setSampleFormat(format, interleaved); + setSuggestedLatency(suggestedLatency); + setHostApiSpecificStreamInfo(hostApiSpecificStreamInfo); + } + + // ----------------------------------------------------------------------------------- + + void DirectionSpecificStreamParameters::setDevice(const Device &device) + { + paStreamParameters_.device = device.index(); + } + + void DirectionSpecificStreamParameters::setNumChannels(int numChannels) + { + paStreamParameters_.channelCount = numChannels; + } + + void DirectionSpecificStreamParameters::setSampleFormat(SampleDataFormat format, bool interleaved) + { + paStreamParameters_.sampleFormat = static_cast(format); + + if (!interleaved) + paStreamParameters_.sampleFormat |= paNonInterleaved; + } + + void DirectionSpecificStreamParameters::setHostApiSpecificSampleFormat(PaSampleFormat format, bool interleaved) + { + paStreamParameters_.sampleFormat = format; + + paStreamParameters_.sampleFormat |= paCustomFormat; + + if (!interleaved) + paStreamParameters_.sampleFormat |= paNonInterleaved; + } + + void DirectionSpecificStreamParameters::setSuggestedLatency(PaTime latency) + { + paStreamParameters_.suggestedLatency = latency; + } + + void DirectionSpecificStreamParameters::setHostApiSpecificStreamInfo(void *streamInfo) + { + paStreamParameters_.hostApiSpecificStreamInfo = streamInfo; + } + + // ----------------------------------------------------------------------------------- + + PaStreamParameters *DirectionSpecificStreamParameters::paStreamParameters() + { + if (paStreamParameters_.channelCount > 0 && paStreamParameters_.device != paNoDevice) + return &paStreamParameters_; + else + return NULL; + } + + const PaStreamParameters *DirectionSpecificStreamParameters::paStreamParameters() const + { + if (paStreamParameters_.channelCount > 0 && paStreamParameters_.device != paNoDevice) + return &paStreamParameters_; + else + return NULL; + } + + Device &DirectionSpecificStreamParameters::device() const + { + return System::instance().deviceByIndex(paStreamParameters_.device); + } + + int DirectionSpecificStreamParameters::numChannels() const + { + return paStreamParameters_.channelCount; + } + + ////// + /// Returns the (non host api-specific) sample format, without including + /// the paNonInterleaved flag. If the sample format is host api-spefific, + /// INVALID_FORMAT (0) will be returned. + ////// + SampleDataFormat DirectionSpecificStreamParameters::sampleFormat() const + { + if (isSampleFormatHostApiSpecific()) + return INVALID_FORMAT; + else + return static_cast(paStreamParameters_.sampleFormat & ~paNonInterleaved); + } + + bool DirectionSpecificStreamParameters::isSampleFormatInterleaved() const + { + return ((paStreamParameters_.sampleFormat & paNonInterleaved) == 0); + } + + bool DirectionSpecificStreamParameters::isSampleFormatHostApiSpecific() const + { + return ((paStreamParameters_.sampleFormat & paCustomFormat) == 0); + } + + ////// + /// Returns the host api-specific sample format, without including any + /// paCustomFormat or paNonInterleaved flags. Will return 0 if the sample format is + /// not host api-specific. + ////// + PaSampleFormat DirectionSpecificStreamParameters::hostApiSpecificSampleFormat() const + { + if (isSampleFormatHostApiSpecific()) + return paStreamParameters_.sampleFormat & ~paCustomFormat & ~paNonInterleaved; + else + return 0; + } + + PaTime DirectionSpecificStreamParameters::suggestedLatency() const + { + return paStreamParameters_.suggestedLatency; + } + + void *DirectionSpecificStreamParameters::hostApiSpecificStreamInfo() const + { + return paStreamParameters_.hostApiSpecificStreamInfo; + } + + // ----------------------------------------------------------------------------------- } // namespace portaudio diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/Exception.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/Exception.cxx index 98945c81724..de8724d6745 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/Exception.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/Exception.cxx @@ -2,122 +2,120 @@ namespace portaudio { - // ----------------------------------------------------------------------------------- - // PaException: - // ----------------------------------------------------------------------------------- - - ////// - /// Wraps a PortAudio error into a PortAudioCpp PaException. - ////// - PaException::PaException(PaError error) : error_(error) - { - } - - // ----------------------------------------------------------------------------------- - - ////// - /// Alias for paErrorText(), to have std::exception compliance. - ////// - const char *PaException::what() const throw() - { - return paErrorText(); - } - - // ----------------------------------------------------------------------------------- - - ////// - /// Returns the PortAudio error code (PaError). - ////// - PaError PaException::paError() const - { - return error_; - } - - ////// - /// Returns the error as a (zero-terminated) text string. - ////// - const char *PaException::paErrorText() const - { - return Pa_GetErrorText(error_); - } - - ////// - /// Returns true is the error is a HostApi error. - ////// - bool PaException::isHostApiError() const - { - return (error_ == paUnanticipatedHostError); - } - - ////// - /// Returns the last HostApi error (which is the current one if - /// isHostApiError() returns true) as an error code. - ////// - long PaException::lastHostApiError() const - { - return Pa_GetLastHostErrorInfo()->errorCode; - } - - ////// - /// Returns the last HostApi error (which is the current one if - /// isHostApiError() returns true) as a (zero-terminated) text - /// string, if it's available. - ////// - const char *PaException::lastHostApiErrorText() const - { - return Pa_GetLastHostErrorInfo()->errorText; - } - - // ----------------------------------------------------------------------------------- - - bool PaException::operator==(const PaException &rhs) const - { - return (error_ == rhs.error_); - } - - bool PaException::operator!=(const PaException &rhs) const - { - return !(*this == rhs); - } - - // ----------------------------------------------------------------------------------- - // PaCppException: - // ----------------------------------------------------------------------------------- - - PaCppException::PaCppException(ExceptionSpecifier specifier) : specifier_(specifier) - { - } - - const char *PaCppException::what() const throw() - { - switch (specifier_) - { - case UNABLE_TO_ADAPT_DEVICE: - { - return "Unable to adapt the given device to the specified host api specific device extension"; - } - } - - return "Unknown exception"; - } - - PaCppException::ExceptionSpecifier PaCppException::specifier() const - { - return specifier_; - } - - bool PaCppException::operator==(const PaCppException &rhs) const - { - return (specifier_ == rhs.specifier_); - } - - bool PaCppException::operator!=(const PaCppException &rhs) const - { - return !(*this == rhs); - } - - // ----------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- + // PaException: + // ----------------------------------------------------------------------------------- + + ////// + /// Wraps a PortAudio error into a PortAudioCpp PaException. + ////// + PaException::PaException(PaError error) : error_(error) + { + } + + // ----------------------------------------------------------------------------------- + + ////// + /// Alias for paErrorText(), to have std::exception compliance. + ////// + const char *PaException::what() const throw() + { + return paErrorText(); + } + + // ----------------------------------------------------------------------------------- + + ////// + /// Returns the PortAudio error code (PaError). + ////// + PaError PaException::paError() const + { + return error_; + } + + ////// + /// Returns the error as a (zero-terminated) text string. + ////// + const char *PaException::paErrorText() const + { + return Pa_GetErrorText(error_); + } + + ////// + /// Returns true is the error is a HostApi error. + ////// + bool PaException::isHostApiError() const + { + return (error_ == paUnanticipatedHostError); + } + + ////// + /// Returns the last HostApi error (which is the current one if + /// isHostApiError() returns true) as an error code. + ////// + long PaException::lastHostApiError() const + { + return Pa_GetLastHostErrorInfo()->errorCode; + } + + ////// + /// Returns the last HostApi error (which is the current one if + /// isHostApiError() returns true) as a (zero-terminated) text + /// string, if it's available. + ////// + const char *PaException::lastHostApiErrorText() const + { + return Pa_GetLastHostErrorInfo()->errorText; + } + + // ----------------------------------------------------------------------------------- + + bool PaException::operator==(const PaException &rhs) const + { + return (error_ == rhs.error_); + } + + bool PaException::operator!=(const PaException &rhs) const + { + return !(*this == rhs); + } + + // ----------------------------------------------------------------------------------- + // PaCppException: + // ----------------------------------------------------------------------------------- + + PaCppException::PaCppException(ExceptionSpecifier specifier) : specifier_(specifier) + { + } + + const char *PaCppException::what() const throw() + { + switch (specifier_) + { + case UNABLE_TO_ADAPT_DEVICE: + { + return "Unable to adapt the given device to the specified host api specific device extension"; + } + } + + return "Unknown exception"; + } + + PaCppException::ExceptionSpecifier PaCppException::specifier() const + { + return specifier_; + } + + bool PaCppException::operator==(const PaCppException &rhs) const + { + return (specifier_ == rhs.specifier_); + } + + bool PaCppException::operator!=(const PaCppException &rhs) const + { + return !(*this == rhs); + } + + // ----------------------------------------------------------------------------------- } // namespace portaudio - - diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/HostApi.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/HostApi.cxx index 6a09670c002..ecc235376c8 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/HostApi.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/HostApi.cxx @@ -8,114 +8,114 @@ namespace portaudio { - // ----------------------------------------------------------------------------------- - - HostApi::HostApi(PaHostApiIndex index) : devices_(NULL) - { - try - { - info_ = Pa_GetHostApiInfo(index); - - // Create and populate devices array: - int numDevices = deviceCount(); - - devices_ = new Device*[numDevices]; - - for (int i = 0; i < numDevices; ++i) - { - PaDeviceIndex deviceIndex = Pa_HostApiDeviceIndexToDeviceIndex(index, i); - - if (deviceIndex < 0) - { - throw PaException(deviceIndex); - } - - devices_[i] = &System::instance().deviceByIndex(deviceIndex); - } - } - catch (const std::exception &e) - { - // Delete any (partially) constructed objects (deconstructor isn't called): - delete[] devices_; // devices_ is either NULL or valid - - // Re-throw exception: - throw e; - } - } - - HostApi::~HostApi() - { - // Destroy devices array: - delete[] devices_; - } - - // ----------------------------------------------------------------------------------- - - PaHostApiTypeId HostApi::typeId() const - { - return info_->type; - } - - PaHostApiIndex HostApi::index() const - { - PaHostApiIndex index = Pa_HostApiTypeIdToHostApiIndex(typeId()); - - if (index < 0) - throw PaException(index); - - return index; - } - - const char *HostApi::name() const - { - return info_->name; - } - - int HostApi::deviceCount() const - { - return info_->deviceCount; - } - - // ----------------------------------------------------------------------------------- - - HostApi::DeviceIterator HostApi::devicesBegin() - { - DeviceIterator tmp; - tmp.ptr_ = &devices_[0]; // begin (first element) - return tmp; - } - - HostApi::DeviceIterator HostApi::devicesEnd() - { - DeviceIterator tmp; - tmp.ptr_ = &devices_[deviceCount()]; // end (one past last element) - return tmp; - } - - // ----------------------------------------------------------------------------------- - - Device &HostApi::defaultInputDevice() const - { - return System::instance().deviceByIndex(info_->defaultInputDevice); - } - - Device &HostApi::defaultOutputDevice() const - { - return System::instance().deviceByIndex(info_->defaultOutputDevice); - } - - // ----------------------------------------------------------------------------------- - - bool HostApi::operator==(const HostApi &rhs) const - { - return (typeId() == rhs.typeId()); - } - - bool HostApi::operator!=(const HostApi &rhs) const - { - return !(*this == rhs); - } - - // ----------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- + + HostApi::HostApi(PaHostApiIndex index) : devices_(NULL) + { + try + { + info_ = Pa_GetHostApiInfo(index); + + // Create and populate devices array: + int numDevices = deviceCount(); + + devices_ = new Device*[numDevices]; + + for (int i = 0; i < numDevices; ++i) + { + PaDeviceIndex deviceIndex = Pa_HostApiDeviceIndexToDeviceIndex(index, i); + + if (deviceIndex < 0) + { + throw PaException(deviceIndex); + } + + devices_[i] = &System::instance().deviceByIndex(deviceIndex); + } + } + catch (const std::exception &e) + { + // Delete any (partially) constructed objects (deconstructor isn't called): + delete[] devices_; // devices_ is either NULL or valid + + // Re-throw exception: + throw e; + } + } + + HostApi::~HostApi() + { + // Destroy devices array: + delete[] devices_; + } + + // ----------------------------------------------------------------------------------- + + PaHostApiTypeId HostApi::typeId() const + { + return info_->type; + } + + PaHostApiIndex HostApi::index() const + { + PaHostApiIndex index = Pa_HostApiTypeIdToHostApiIndex(typeId()); + + if (index < 0) + throw PaException(index); + + return index; + } + + const char *HostApi::name() const + { + return info_->name; + } + + int HostApi::deviceCount() const + { + return info_->deviceCount; + } + + // ----------------------------------------------------------------------------------- + + HostApi::DeviceIterator HostApi::devicesBegin() + { + DeviceIterator tmp; + tmp.ptr_ = &devices_[0]; // begin (first element) + return tmp; + } + + HostApi::DeviceIterator HostApi::devicesEnd() + { + DeviceIterator tmp; + tmp.ptr_ = &devices_[deviceCount()]; // end (one past last element) + return tmp; + } + + // ----------------------------------------------------------------------------------- + + Device &HostApi::defaultInputDevice() const + { + return System::instance().deviceByIndex(info_->defaultInputDevice); + } + + Device &HostApi::defaultOutputDevice() const + { + return System::instance().deviceByIndex(info_->defaultOutputDevice); + } + + // ----------------------------------------------------------------------------------- + + bool HostApi::operator==(const HostApi &rhs) const + { + return (typeId() == rhs.typeId()); + } + + bool HostApi::operator!=(const HostApi &rhs) const + { + return !(*this == rhs); + } + + // ----------------------------------------------------------------------------------- } // namespace portaudio diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/InterfaceCallbackStream.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/InterfaceCallbackStream.cxx index 5433fa37321..fa761aa4d21 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/InterfaceCallbackStream.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/InterfaceCallbackStream.cxx @@ -7,39 +7,39 @@ namespace portaudio { - // ---------------------------------------------------------------------------------== - - InterfaceCallbackStream::InterfaceCallbackStream() - { - } - - InterfaceCallbackStream::InterfaceCallbackStream(const StreamParameters ¶meters, CallbackInterface &instance) - { - open(parameters, instance); - } - - InterfaceCallbackStream::~InterfaceCallbackStream() - { - try - { - close(); - } - catch (...) - { - // ignore all errors - } - } - - // ---------------------------------------------------------------------------------== - - void InterfaceCallbackStream::open(const StreamParameters ¶meters, CallbackInterface &instance) - { - PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), - parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), &impl::callbackInterfaceToPaCallbackAdapter, static_cast(&instance)); - - if (err != paNoError) - { - throw PaException(err); - } - } + // ---------------------------------------------------------------------------------== + + InterfaceCallbackStream::InterfaceCallbackStream() + { + } + + InterfaceCallbackStream::InterfaceCallbackStream(const StreamParameters ¶meters, CallbackInterface &instance) + { + open(parameters, instance); + } + + InterfaceCallbackStream::~InterfaceCallbackStream() + { + try + { + close(); + } + catch (...) + { + // ignore all errors + } + } + + // ---------------------------------------------------------------------------------== + + void InterfaceCallbackStream::open(const StreamParameters ¶meters, CallbackInterface &instance) + { + PaError err = Pa_OpenStream(&stream_, parameters.inputParameters().paStreamParameters(), parameters.outputParameters().paStreamParameters(), + parameters.sampleRate(), parameters.framesPerBuffer(), parameters.flags(), &impl::callbackInterfaceToPaCallbackAdapter, static_cast(&instance)); + + if (err != paNoError) + { + throw PaException(err); + } + } } diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/MemFunCallbackStream.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/MemFunCallbackStream.cxx index 5141de2aba0..4f955641eed 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/MemFunCallbackStream.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/MemFunCallbackStream.cxx @@ -1,4 +1,3 @@ #include "portaudiocpp/MemFunCallbackStream.hxx" // (... template class ...) - diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/Stream.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/Stream.cxx index ba16e0335f9..c16a13c6f40 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/Stream.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/Stream.cxx @@ -8,188 +8,188 @@ namespace portaudio { - // ----------------------------------------------------------------------------------- - - Stream::Stream() : stream_(NULL) - { - } - - Stream::~Stream() - { - // (can't call close here, - // the derived class should atleast call - // close() in it's deconstructor) - } - - // ----------------------------------------------------------------------------------- - - ////// - /// Closes the Stream if it's open, else does nothing. - ////// - void Stream::close() - { - if (isOpen() && System::exists()) - { - PaError err = Pa_CloseStream(stream_); - stream_ = NULL; - - if (err != paNoError) - throw PaException(err); - } - } - - ////// - /// Returns true if the Stream is open. - ////// - bool Stream::isOpen() const - { - return (stream_ != NULL); - } - - // ----------------------------------------------------------------------------------- - - void Stream::setStreamFinishedCallback(PaStreamFinishedCallback *callback) - { - PaError err = Pa_SetStreamFinishedCallback(stream_, callback); - - if (err != paNoError) - throw PaException(err); - } - - // ----------------------------------------------------------------------------------- - - void Stream::start() - { - PaError err = Pa_StartStream(stream_); - - if (err != paNoError) - throw PaException(err); - } - - void Stream::stop() - { - PaError err = Pa_StopStream(stream_); - - if (err != paNoError) - throw PaException(err); - } - - void Stream::abort() - { - PaError err = Pa_AbortStream(stream_); - - if (err != paNoError) - throw PaException(err); - } - - bool Stream::isStopped() const - { - PaError ret = Pa_IsStreamStopped(stream_); - - if (ret < 0) - throw PaException(ret); - - return (ret == 1); - } - - bool Stream::isActive() const - { - PaError ret = Pa_IsStreamActive(stream_); - - if (ret < 0) - throw PaException(ret); - - return (ret == 1); - } - - // ----------------------------------------------------------------------------------- - - ////// - /// Returns the best known input latency for the Stream. This value may differ from the - /// suggested input latency set in the StreamParameters. Includes all sources of - /// latency known to PortAudio such as internal buffering, and Host API reported latency. - /// Doesn't include any estimates of unknown latency. - ////// - PaTime Stream::inputLatency() const - { - const PaStreamInfo *info = Pa_GetStreamInfo(stream_); - if (info == NULL) - { - throw PaException(paInternalError); - return PaTime(0.0); - } - - return info->inputLatency; - } - - ////// - /// Returns the best known output latency for the Stream. This value may differ from the - /// suggested output latency set in the StreamParameters. Includes all sources of - /// latency known to PortAudio such as internal buffering, and Host API reported latency. - /// Doesn't include any estimates of unknown latency. - ////// - PaTime Stream::outputLatency() const - { - const PaStreamInfo *info = Pa_GetStreamInfo(stream_); - if (info == NULL) - { - throw PaException(paInternalError); - return PaTime(0.0); - } - - return info->outputLatency; - } - - ////// - /// Returns the sample rate of the Stream. Usually this will be the - /// best known estimate of the used sample rate. For instance when opening a - /// Stream setting 44100.0 Hz in the StreamParameters, the actual sample - /// rate might be something like 44103.2 Hz (due to imperfections in the - /// sound card hardware). - ////// - double Stream::sampleRate() const - { - const PaStreamInfo *info = Pa_GetStreamInfo(stream_); - if (info == NULL) - { - throw PaException(paInternalError); - return 0.0; - } - - return info->sampleRate; - } - - // ----------------------------------------------------------------------------------- - - PaTime Stream::time() const - { - return Pa_GetStreamTime(stream_); - } - - // ----------------------------------------------------------------------------------- - - ////// - /// Accessor (const) for PortAudio PaStream pointer, useful for interfacing with - /// PortAudio add-ons such as PortMixer for instance. Normally accessing this - /// pointer should not be needed as PortAudioCpp aims to provide all of PortAudio's - /// functionality. - ////// - const PaStream *Stream::paStream() const - { - return stream_; - } - - ////// - /// Accessor (non-const) for PortAudio PaStream pointer, useful for interfacing with - /// PortAudio add-ons such as PortMixer for instance. Normally accessing this - /// pointer should not be needed as PortAudioCpp aims to provide all of PortAudio's - /// functionality. - ////// - PaStream *Stream::paStream() - { - return stream_; - } - - // ----------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- + + Stream::Stream() : stream_(NULL) + { + } + + Stream::~Stream() + { + // (can't call close here, + // the derived class should atleast call + // close() in it's deconstructor) + } + + // ----------------------------------------------------------------------------------- + + ////// + /// Closes the Stream if it's open, else does nothing. + ////// + void Stream::close() + { + if (isOpen() && System::exists()) + { + PaError err = Pa_CloseStream(stream_); + stream_ = NULL; + + if (err != paNoError) + throw PaException(err); + } + } + + ////// + /// Returns true if the Stream is open. + ////// + bool Stream::isOpen() const + { + return (stream_ != NULL); + } + + // ----------------------------------------------------------------------------------- + + void Stream::setStreamFinishedCallback(PaStreamFinishedCallback *callback) + { + PaError err = Pa_SetStreamFinishedCallback(stream_, callback); + + if (err != paNoError) + throw PaException(err); + } + + // ----------------------------------------------------------------------------------- + + void Stream::start() + { + PaError err = Pa_StartStream(stream_); + + if (err != paNoError) + throw PaException(err); + } + + void Stream::stop() + { + PaError err = Pa_StopStream(stream_); + + if (err != paNoError) + throw PaException(err); + } + + void Stream::abort() + { + PaError err = Pa_AbortStream(stream_); + + if (err != paNoError) + throw PaException(err); + } + + bool Stream::isStopped() const + { + PaError ret = Pa_IsStreamStopped(stream_); + + if (ret < 0) + throw PaException(ret); + + return (ret == 1); + } + + bool Stream::isActive() const + { + PaError ret = Pa_IsStreamActive(stream_); + + if (ret < 0) + throw PaException(ret); + + return (ret == 1); + } + + // ----------------------------------------------------------------------------------- + + ////// + /// Returns the best known input latency for the Stream. This value may differ from the + /// suggested input latency set in the StreamParameters. Includes all sources of + /// latency known to PortAudio such as internal buffering, and Host API reported latency. + /// Doesn't include any estimates of unknown latency. + ////// + PaTime Stream::inputLatency() const + { + const PaStreamInfo *info = Pa_GetStreamInfo(stream_); + if (info == NULL) + { + throw PaException(paInternalError); + return PaTime(0.0); + } + + return info->inputLatency; + } + + ////// + /// Returns the best known output latency for the Stream. This value may differ from the + /// suggested output latency set in the StreamParameters. Includes all sources of + /// latency known to PortAudio such as internal buffering, and Host API reported latency. + /// Doesn't include any estimates of unknown latency. + ////// + PaTime Stream::outputLatency() const + { + const PaStreamInfo *info = Pa_GetStreamInfo(stream_); + if (info == NULL) + { + throw PaException(paInternalError); + return PaTime(0.0); + } + + return info->outputLatency; + } + + ////// + /// Returns the sample rate of the Stream. Usually this will be the + /// best known estimate of the used sample rate. For instance when opening a + /// Stream setting 44100.0 Hz in the StreamParameters, the actual sample + /// rate might be something like 44103.2 Hz (due to imperfections in the + /// sound card hardware). + ////// + double Stream::sampleRate() const + { + const PaStreamInfo *info = Pa_GetStreamInfo(stream_); + if (info == NULL) + { + throw PaException(paInternalError); + return 0.0; + } + + return info->sampleRate; + } + + // ----------------------------------------------------------------------------------- + + PaTime Stream::time() const + { + return Pa_GetStreamTime(stream_); + } + + // ----------------------------------------------------------------------------------- + + ////// + /// Accessor (const) for PortAudio PaStream pointer, useful for interfacing with + /// PortAudio add-ons such as PortMixer for instance. Normally accessing this + /// pointer should not be needed as PortAudioCpp aims to provide all of PortAudio's + /// functionality. + ////// + const PaStream *Stream::paStream() const + { + return stream_; + } + + ////// + /// Accessor (non-const) for PortAudio PaStream pointer, useful for interfacing with + /// PortAudio add-ons such as PortMixer for instance. Normally accessing this + /// pointer should not be needed as PortAudioCpp aims to provide all of PortAudio's + /// functionality. + ////// + PaStream *Stream::paStream() + { + return stream_; + } + + // ----------------------------------------------------------------------------------- } // namespace portaudio diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/StreamParameters.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/StreamParameters.cxx index 5b9e89716a2..11de3094d52 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/StreamParameters.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/StreamParameters.cxx @@ -6,160 +6,155 @@ namespace portaudio { - // ----------------------------------------------------------------------------------- - - ////// - /// Default constructor; does nothing. - ////// - StreamParameters::StreamParameters() - { - } - - ////// - /// Sets up the all parameters needed to open either a half-duplex or full-duplex Stream. - /// - /// @param inputParameters The parameters for the input direction of the to-be opened - /// Stream or DirectionSpecificStreamParameters::null() for an output-only Stream. - /// @param outputParameters The parameters for the output direction of the to-be opened - /// Stream or DirectionSpecificStreamParameters::null() for an input-only Stream. - /// @param sampleRate The to-be opened Stream's sample rate in Hz. - /// @param framesPerBuffer The number of frames per buffer for a CallbackStream, or - /// the preferred buffer granularity for a BlockingStream. - /// @param flags The flags for the to-be opened Stream; default paNoFlag. - ////// - StreamParameters::StreamParameters(const DirectionSpecificStreamParameters &inputParameters, - const DirectionSpecificStreamParameters &outputParameters, double sampleRate, unsigned long framesPerBuffer, - PaStreamFlags flags) : inputParameters_(inputParameters), outputParameters_(outputParameters), - sampleRate_(sampleRate), framesPerBuffer_(framesPerBuffer), flags_(flags) - { - } - - // ----------------------------------------------------------------------------------- - - ////// - /// Sets the requested sample rate. If this sample rate isn't supported by the hardware, the - /// Stream will fail to open. The real-life sample rate used might differ slightly due to - /// imperfections in the sound card hardware; use Stream::sampleRate() to retreive the - /// best known estimate for this value. - ////// - void StreamParameters::setSampleRate(double sampleRate) - { - sampleRate_ = sampleRate; - } - - ////// - /// Either the number of frames per buffer for a CallbackStream, or - /// the preferred buffer granularity for a BlockingStream. See PortAudio - /// documentation. - ////// - void StreamParameters::setFramesPerBuffer(unsigned long framesPerBuffer) - { - framesPerBuffer_ = framesPerBuffer; - } - - ////// - /// Sets the specified flag or does nothing when the flag is already set. Doesn't - /// `unset' any previously existing flags (use clearFlags() for that). - ////// - void StreamParameters::setFlag(PaStreamFlags flag) - { - flags_ |= flag; - } - - ////// - /// Unsets the specified flag or does nothing if the flag isn't set. Doesn't affect - /// any other flags. - ////// - void StreamParameters::unsetFlag(PaStreamFlags flag) - { - flags_ &= ~flag; - } - - ////// - /// Clears or `unsets' all set flags. - ////// - void StreamParameters::clearFlags() - { - flags_ = paNoFlag; - } - - // ----------------------------------------------------------------------------------- - - void StreamParameters::setInputParameters(const DirectionSpecificStreamParameters ¶meters) - { - inputParameters_ = parameters; - } - - void StreamParameters::setOutputParameters(const DirectionSpecificStreamParameters ¶meters) - { - outputParameters_ = parameters; - } - - // ----------------------------------------------------------------------------------- - - bool StreamParameters::isSupported() const - { - return (Pa_IsFormatSupported(inputParameters_.paStreamParameters(), - outputParameters_.paStreamParameters(), sampleRate_) == paFormatIsSupported); - } - - // ----------------------------------------------------------------------------------- - - double StreamParameters::sampleRate() const - { - return sampleRate_; - } - - unsigned long StreamParameters::framesPerBuffer() const - { - return framesPerBuffer_; - } - - ////// - /// Returns all currently set flags as a binary combined - /// integer value (PaStreamFlags). Use isFlagSet() to - /// avoid dealing with the bitmasks. - ////// - PaStreamFlags StreamParameters::flags() const - { - return flags_; - } - - ////// - /// Returns true if the specified flag is currently set - /// or false if it isn't. - ////// - bool StreamParameters::isFlagSet(PaStreamFlags flag) const - { - return ((flags_ & flag) != 0); - } - - // ----------------------------------------------------------------------------------- - - DirectionSpecificStreamParameters &StreamParameters::inputParameters() - { - return inputParameters_; - } - - const DirectionSpecificStreamParameters &StreamParameters::inputParameters() const - { - return inputParameters_; - } - - DirectionSpecificStreamParameters &StreamParameters::outputParameters() - { - return outputParameters_; - } - - const DirectionSpecificStreamParameters &StreamParameters::outputParameters() const - { - return outputParameters_; - } - - // ----------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- + + ////// + /// Default constructor; does nothing. + ////// + StreamParameters::StreamParameters() + { + } + + ////// + /// Sets up the all parameters needed to open either a half-duplex or full-duplex Stream. + /// + /// @param inputParameters The parameters for the input direction of the to-be opened + /// Stream or DirectionSpecificStreamParameters::null() for an output-only Stream. + /// @param outputParameters The parameters for the output direction of the to-be opened + /// Stream or DirectionSpecificStreamParameters::null() for an input-only Stream. + /// @param sampleRate The to-be opened Stream's sample rate in Hz. + /// @param framesPerBuffer The number of frames per buffer for a CallbackStream, or + /// the preferred buffer granularity for a BlockingStream. + /// @param flags The flags for the to-be opened Stream; default paNoFlag. + ////// + StreamParameters::StreamParameters(const DirectionSpecificStreamParameters &inputParameters, + const DirectionSpecificStreamParameters &outputParameters, double sampleRate, unsigned long framesPerBuffer, + PaStreamFlags flags) : inputParameters_(inputParameters), outputParameters_(outputParameters), + sampleRate_(sampleRate), framesPerBuffer_(framesPerBuffer), flags_(flags) + { + } + + // ----------------------------------------------------------------------------------- + + ////// + /// Sets the requested sample rate. If this sample rate isn't supported by the hardware, the + /// Stream will fail to open. The real-life sample rate used might differ slightly due to + /// imperfections in the sound card hardware; use Stream::sampleRate() to retrieve the + /// best known estimate for this value. + ////// + void StreamParameters::setSampleRate(double sampleRate) + { + sampleRate_ = sampleRate; + } + + ////// + /// Either the number of frames per buffer for a CallbackStream, or + /// the preferred buffer granularity for a BlockingStream. See PortAudio + /// documentation. + ////// + void StreamParameters::setFramesPerBuffer(unsigned long framesPerBuffer) + { + framesPerBuffer_ = framesPerBuffer; + } + + ////// + /// Sets the specified flag or does nothing when the flag is already set. Doesn't + /// `unset' any previously existing flags (use clearFlags() for that). + ////// + void StreamParameters::setFlag(PaStreamFlags flag) + { + flags_ |= flag; + } + + ////// + /// Unsets the specified flag or does nothing if the flag isn't set. Doesn't affect + /// any other flags. + ////// + void StreamParameters::unsetFlag(PaStreamFlags flag) + { + flags_ &= ~flag; + } + + ////// + /// Clears or `unsets' all set flags. + ////// + void StreamParameters::clearFlags() + { + flags_ = paNoFlag; + } + + // ----------------------------------------------------------------------------------- + + void StreamParameters::setInputParameters(const DirectionSpecificStreamParameters ¶meters) + { + inputParameters_ = parameters; + } + + void StreamParameters::setOutputParameters(const DirectionSpecificStreamParameters ¶meters) + { + outputParameters_ = parameters; + } + + // ----------------------------------------------------------------------------------- + + bool StreamParameters::isSupported() const + { + return (Pa_IsFormatSupported(inputParameters_.paStreamParameters(), + outputParameters_.paStreamParameters(), sampleRate_) == paFormatIsSupported); + } + + // ----------------------------------------------------------------------------------- + + double StreamParameters::sampleRate() const + { + return sampleRate_; + } + + unsigned long StreamParameters::framesPerBuffer() const + { + return framesPerBuffer_; + } + + ////// + /// Returns all currently set flags as a binary combined + /// integer value (PaStreamFlags). Use isFlagSet() to + /// avoid dealing with the bitmasks. + ////// + PaStreamFlags StreamParameters::flags() const + { + return flags_; + } + + ////// + /// Returns true if the specified flag is currently set + /// or false if it isn't. + ////// + bool StreamParameters::isFlagSet(PaStreamFlags flag) const + { + return ((flags_ & flag) != 0); + } + + // ----------------------------------------------------------------------------------- + + DirectionSpecificStreamParameters &StreamParameters::inputParameters() + { + return inputParameters_; + } + + const DirectionSpecificStreamParameters &StreamParameters::inputParameters() const + { + return inputParameters_; + } + + DirectionSpecificStreamParameters &StreamParameters::outputParameters() + { + return outputParameters_; + } + + const DirectionSpecificStreamParameters &StreamParameters::outputParameters() const + { + return outputParameters_; + } + + // ----------------------------------------------------------------------------------- } // namespace portaudio - - - - - diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/System.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/System.cxx index acb419d4aa8..1e03dc884a7 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/System.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/System.cxx @@ -12,297 +12,296 @@ namespace portaudio { - // ----------------------------------------------------------------------------------- - - // Static members: - System *System::instance_ = NULL; - int System::initCount_ = 0; - HostApi **System::hostApis_ = NULL; - Device **System::devices_ = NULL; - Device *System::nullDevice_ = NULL; - - // ----------------------------------------------------------------------------------- - - int System::version() - { - return Pa_GetVersion(); - } - - const char *System::versionText() - { - return Pa_GetVersionText(); - } - - void System::initialize() - { - ++initCount_; - - if (initCount_ == 1) - { - // Create singleton: - assert(instance_ == NULL); - instance_ = new System(); - - // Initialize the PortAudio system: - { - PaError err = Pa_Initialize(); - - if (err != paNoError) - throw PaException(err); - } - - // Create and populate device array: - { - int numDevices = instance().deviceCount(); - - devices_ = new Device*[numDevices]; - - for (int i = 0; i < numDevices; ++i) - devices_[i] = new Device(i); - } - - // Create and populate host api array: - { - int numHostApis = instance().hostApiCount(); - - hostApis_ = new HostApi*[numHostApis]; - - for (int i = 0; i < numHostApis; ++i) - hostApis_[i] = new HostApi(i); - } - - // Create null device: - nullDevice_ = new Device(paNoDevice); - } - } - - void System::terminate() - { - PaError err = paNoError; - - if (initCount_ == 1) - { - // Destroy null device: - delete nullDevice_; - - // Destroy host api array: - { - if (hostApis_ != NULL) - { - int numHostApis = instance().hostApiCount(); - - for (int i = 0; i < numHostApis; ++i) - delete hostApis_[i]; - - delete[] hostApis_; - hostApis_ = NULL; - } - } + // ----------------------------------------------------------------------------------- + + // Static members: + System *System::instance_ = NULL; + int System::initCount_ = 0; + HostApi **System::hostApis_ = NULL; + Device **System::devices_ = NULL; + Device *System::nullDevice_ = NULL; + + // ----------------------------------------------------------------------------------- + + int System::version() + { + return Pa_GetVersion(); + } + + const char *System::versionText() + { + return Pa_GetVersionText(); + } + + void System::initialize() + { + ++initCount_; - // Destroy device array: - { - if (devices_ != NULL) - { - int numDevices = instance().deviceCount(); + if (initCount_ == 1) + { + // Create singleton: + assert(instance_ == NULL); + instance_ = new System(); - for (int i = 0; i < numDevices; ++i) - delete devices_[i]; + // Initialize the PortAudio system: + { + PaError err = Pa_Initialize(); - delete[] devices_; - devices_ = NULL; - } - } + if (err != paNoError) + throw PaException(err); + } - // Terminate the PortAudio system: - assert(instance_ != NULL); - err = Pa_Terminate(); + // Create and populate device array: + { + int numDevices = instance().deviceCount(); - // Destroy singleton: - delete instance_; - instance_ = NULL; - } + devices_ = new Device*[numDevices]; + + for (int i = 0; i < numDevices; ++i) + devices_[i] = new Device(i); + } + + // Create and populate host api array: + { + int numHostApis = instance().hostApiCount(); + + hostApis_ = new HostApi*[numHostApis]; - if (initCount_ > 0) - --initCount_; - - if (err != paNoError) - throw PaException(err); - } - - - System &System::instance() - { - assert(exists()); - - return *instance_; - } - - bool System::exists() - { - return (instance_ != NULL); - } - - // ----------------------------------------------------------------------------------- - - System::HostApiIterator System::hostApisBegin() - { - System::HostApiIterator tmp; - tmp.ptr_ = &hostApis_[0]; // begin (first element) - return tmp; - } - - System::HostApiIterator System::hostApisEnd() - { - int count = hostApiCount(); - - System::HostApiIterator tmp; - tmp.ptr_ = &hostApis_[count]; // end (one past last element) - return tmp; - } - - HostApi &System::defaultHostApi() - { - PaHostApiIndex defaultHostApi = Pa_GetDefaultHostApi(); - - if (defaultHostApi < 0) - throw PaException(defaultHostApi); - - return *hostApis_[defaultHostApi]; - } - - HostApi &System::hostApiByTypeId(PaHostApiTypeId type) - { - PaHostApiIndex index = Pa_HostApiTypeIdToHostApiIndex(type); - - if (index < 0) - throw PaException(index); - - return *hostApis_[index]; - } - - HostApi &System::hostApiByIndex(PaHostApiIndex index) - { - if (index < 0 || index >= hostApiCount()) - throw PaException(paInternalError); - - return *hostApis_[index]; - } - - int System::hostApiCount() - { - PaHostApiIndex count = Pa_GetHostApiCount(); - - if (count < 0) - throw PaException(count); - - return count; - } - - // ----------------------------------------------------------------------------------- - - System::DeviceIterator System::devicesBegin() - { - DeviceIterator tmp; - tmp.ptr_ = &devices_[0]; - - return tmp; - } - - System::DeviceIterator System::devicesEnd() - { - int count = deviceCount(); - - DeviceIterator tmp; - tmp.ptr_ = &devices_[count]; - - return tmp; - } - - ////// - /// Returns the System's default input Device, or the null Device if none - /// was available. - ////// - Device &System::defaultInputDevice() - { - PaDeviceIndex index = Pa_GetDefaultInputDevice(); - return deviceByIndex(index); - } - - ////// - /// Returns the System's default output Device, or the null Device if none - /// was available. - ////// - Device &System::defaultOutputDevice() - { - PaDeviceIndex index = Pa_GetDefaultOutputDevice(); - return deviceByIndex(index); - } - - ////// - /// Returns the Device for the given index. - /// Will throw a paInternalError equivalent PaException if the given index - /// is out of range. - ////// - Device &System::deviceByIndex(PaDeviceIndex index) - { - if (index < -1 || index >= deviceCount()) - { - throw PaException(paInternalError); - } - - if (index == -1) - return System::instance().nullDevice(); - - return *devices_[index]; - } - - int System::deviceCount() - { - PaDeviceIndex count = Pa_GetDeviceCount(); - - if (count < 0) - throw PaException(count); - - return count; - } - - Device &System::nullDevice() - { - return *nullDevice_; - } - - // ----------------------------------------------------------------------------------- - - void System::sleep(long msec) - { - Pa_Sleep(msec); - } - - int System::sizeOfSample(PaSampleFormat format) - { - PaError err = Pa_GetSampleSize(format); - if (err < 0) - { - throw PaException(err); - return 0; - } - - return err; - } - - // ----------------------------------------------------------------------------------- - - System::System() - { - // (left blank intentionally) - } - - System::~System() - { - // (left blank intentionally) - } - - // ----------------------------------------------------------------------------------- + for (int i = 0; i < numHostApis; ++i) + hostApis_[i] = new HostApi(i); + } -} // namespace portaudio + // Create null device: + nullDevice_ = new Device(paNoDevice); + } + } + + void System::terminate() + { + PaError err = paNoError; + + if (initCount_ == 1) + { + // Destroy null device: + delete nullDevice_; + + // Destroy host api array: + { + if (hostApis_ != NULL) + { + int numHostApis = instance().hostApiCount(); + + for (int i = 0; i < numHostApis; ++i) + delete hostApis_[i]; + + delete[] hostApis_; + hostApis_ = NULL; + } + } + + // Destroy device array: + { + if (devices_ != NULL) + { + int numDevices = instance().deviceCount(); + + for (int i = 0; i < numDevices; ++i) + delete devices_[i]; + + delete[] devices_; + devices_ = NULL; + } + } + // Terminate the PortAudio system: + assert(instance_ != NULL); + err = Pa_Terminate(); + + // Destroy singleton: + delete instance_; + instance_ = NULL; + } + + if (initCount_ > 0) + --initCount_; + + if (err != paNoError) + throw PaException(err); + } + + + System &System::instance() + { + assert(exists()); + + return *instance_; + } + + bool System::exists() + { + return (instance_ != NULL); + } + + // ----------------------------------------------------------------------------------- + + System::HostApiIterator System::hostApisBegin() + { + System::HostApiIterator tmp; + tmp.ptr_ = &hostApis_[0]; // begin (first element) + return tmp; + } + + System::HostApiIterator System::hostApisEnd() + { + int count = hostApiCount(); + + System::HostApiIterator tmp; + tmp.ptr_ = &hostApis_[count]; // end (one past last element) + return tmp; + } + + HostApi &System::defaultHostApi() + { + PaHostApiIndex defaultHostApi = Pa_GetDefaultHostApi(); + + if (defaultHostApi < 0) + throw PaException(defaultHostApi); + + return *hostApis_[defaultHostApi]; + } + + HostApi &System::hostApiByTypeId(PaHostApiTypeId type) + { + PaHostApiIndex index = Pa_HostApiTypeIdToHostApiIndex(type); + + if (index < 0) + throw PaException(index); + + return *hostApis_[index]; + } + + HostApi &System::hostApiByIndex(PaHostApiIndex index) + { + if (index < 0 || index >= hostApiCount()) + throw PaException(paInternalError); + + return *hostApis_[index]; + } + + int System::hostApiCount() + { + PaHostApiIndex count = Pa_GetHostApiCount(); + + if (count < 0) + throw PaException(count); + + return count; + } + + // ----------------------------------------------------------------------------------- + + System::DeviceIterator System::devicesBegin() + { + DeviceIterator tmp; + tmp.ptr_ = &devices_[0]; + + return tmp; + } + + System::DeviceIterator System::devicesEnd() + { + int count = deviceCount(); + + DeviceIterator tmp; + tmp.ptr_ = &devices_[count]; + + return tmp; + } + + ////// + /// Returns the System's default input Device, or the null Device if none + /// was available. + ////// + Device &System::defaultInputDevice() + { + PaDeviceIndex index = Pa_GetDefaultInputDevice(); + return deviceByIndex(index); + } + + ////// + /// Returns the System's default output Device, or the null Device if none + /// was available. + ////// + Device &System::defaultOutputDevice() + { + PaDeviceIndex index = Pa_GetDefaultOutputDevice(); + return deviceByIndex(index); + } + + ////// + /// Returns the Device for the given index. + /// Will throw a paInternalError equivalent PaException if the given index + /// is out of range. + ////// + Device &System::deviceByIndex(PaDeviceIndex index) + { + if (index < -1 || index >= deviceCount()) + { + throw PaException(paInternalError); + } + + if (index == -1) + return System::instance().nullDevice(); + + return *devices_[index]; + } + + int System::deviceCount() + { + PaDeviceIndex count = Pa_GetDeviceCount(); + + if (count < 0) + throw PaException(count); + + return count; + } + + Device &System::nullDevice() + { + return *nullDevice_; + } + + // ----------------------------------------------------------------------------------- + + void System::sleep(long msec) + { + Pa_Sleep(msec); + } + + int System::sizeOfSample(PaSampleFormat format) + { + PaError err = Pa_GetSampleSize(format); + if (err < 0) + { + throw PaException(err); + return 0; + } + + return err; + } + + // ----------------------------------------------------------------------------------- + + System::System() + { + // (left blank intentionally) + } + + System::~System() + { + // (left blank intentionally) + } + + // ----------------------------------------------------------------------------------- + +} // namespace portaudio diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/SystemDeviceIterator.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/SystemDeviceIterator.cxx index f94cf10aab2..72dddbc32e2 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/SystemDeviceIterator.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/SystemDeviceIterator.cxx @@ -2,59 +2,57 @@ namespace portaudio { - // ----------------------------------------------------------------------------------- - - Device &System::DeviceIterator::operator*() const - { - return **ptr_; - } - - Device *System::DeviceIterator::operator->() const - { - return &**this; - } - - // ----------------------------------------------------------------------------------- - - System::DeviceIterator &System::DeviceIterator::operator++() - { - ++ptr_; - return *this; - } - - System::DeviceIterator System::DeviceIterator::operator++(int) - { - System::DeviceIterator prev = *this; - ++*this; - return prev; - } - - System::DeviceIterator &System::DeviceIterator::operator--() - { - --ptr_; - return *this; - } - - System::DeviceIterator System::DeviceIterator::operator--(int) - { - System::DeviceIterator prev = *this; - --*this; - return prev; - } - - // ----------------------------------------------------------------------------------- - - bool System::DeviceIterator::operator==(const System::DeviceIterator &rhs) const - { - return (ptr_ == rhs.ptr_); - } - - bool System::DeviceIterator::operator!=(const System::DeviceIterator &rhs) const - { - return !(*this == rhs); - } - - // ----------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- + + Device &System::DeviceIterator::operator*() const + { + return **ptr_; + } + + Device *System::DeviceIterator::operator->() const + { + return &**this; + } + + // ----------------------------------------------------------------------------------- + + System::DeviceIterator &System::DeviceIterator::operator++() + { + ++ptr_; + return *this; + } + + System::DeviceIterator System::DeviceIterator::operator++(int) + { + System::DeviceIterator prev = *this; + ++*this; + return prev; + } + + System::DeviceIterator &System::DeviceIterator::operator--() + { + --ptr_; + return *this; + } + + System::DeviceIterator System::DeviceIterator::operator--(int) + { + System::DeviceIterator prev = *this; + --*this; + return prev; + } + + // ----------------------------------------------------------------------------------- + + bool System::DeviceIterator::operator==(const System::DeviceIterator &rhs) const + { + return (ptr_ == rhs.ptr_); + } + + bool System::DeviceIterator::operator!=(const System::DeviceIterator &rhs) const + { + return !(*this == rhs); + } + + // ----------------------------------------------------------------------------------- } // namespace portaudio - - diff --git a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/SystemHostApiIterator.cxx b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/SystemHostApiIterator.cxx index 03f2d6e47bd..bca25fc1d49 100644 --- a/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/SystemHostApiIterator.cxx +++ b/3rdparty/portaudio/bindings/cpp/source/portaudiocpp/SystemHostApiIterator.cxx @@ -2,58 +2,57 @@ namespace portaudio { - // ----------------------------------------------------------------------------------- - - HostApi &System::HostApiIterator::operator*() const - { - return **ptr_; - } - - HostApi *System::HostApiIterator::operator->() const - { - return &**this; - } - - // ----------------------------------------------------------------------------------- - - System::HostApiIterator &System::HostApiIterator::operator++() - { - ++ptr_; - return *this; - } - - System::HostApiIterator System::HostApiIterator::operator++(int) - { - System::HostApiIterator prev = *this; - ++*this; - return prev; - } - - System::HostApiIterator &System::HostApiIterator::operator--() - { - --ptr_; - return *this; - } - - System::HostApiIterator System::HostApiIterator::operator--(int) - { - System::HostApiIterator prev = *this; - --*this; - return prev; - } - - // ----------------------------------------------------------------------------------- - - bool System::HostApiIterator::operator==(const System::HostApiIterator &rhs) const - { - return (ptr_ == rhs.ptr_); - } - - bool System::HostApiIterator::operator!=(const System::HostApiIterator &rhs) const - { - return !(*this == rhs); - } - - // ----------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- + + HostApi &System::HostApiIterator::operator*() const + { + return **ptr_; + } + + HostApi *System::HostApiIterator::operator->() const + { + return &**this; + } + + // ----------------------------------------------------------------------------------- + + System::HostApiIterator &System::HostApiIterator::operator++() + { + ++ptr_; + return *this; + } + + System::HostApiIterator System::HostApiIterator::operator++(int) + { + System::HostApiIterator prev = *this; + ++*this; + return prev; + } + + System::HostApiIterator &System::HostApiIterator::operator--() + { + --ptr_; + return *this; + } + + System::HostApiIterator System::HostApiIterator::operator--(int) + { + System::HostApiIterator prev = *this; + --*this; + return prev; + } + + // ----------------------------------------------------------------------------------- + + bool System::HostApiIterator::operator==(const System::HostApiIterator &rhs) const + { + return (ptr_ == rhs.ptr_); + } + + bool System::HostApiIterator::operator!=(const System::HostApiIterator &rhs) const + { + return !(*this == rhs); + } + + // ----------------------------------------------------------------------------------- } // namespace portaudio - diff --git a/3rdparty/portaudio/cmake/PortAudioConfig.cmake.in b/3rdparty/portaudio/cmake/PortAudioConfig.cmake.in new file mode 100644 index 00000000000..ce50d159db0 --- /dev/null +++ b/3rdparty/portaudio/cmake/PortAudioConfig.cmake.in @@ -0,0 +1,18 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/PortAudioTargets.cmake") + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/modules") + +include(CMakeFindDependencyMacro) + +find_dependency(Threads) + +if("@PA_USE_JACK@") + find_dependency(Regex) + find_dependency(JACK) +endif() + +if("@PA_USE_ALSA@") + find_dependency(ALSA) +endif() diff --git a/3rdparty/portaudio/cmake/cmake_uninstall.cmake.in b/3rdparty/portaudio/cmake/cmake_uninstall.cmake.in new file mode 100644 index 00000000000..2037e365393 --- /dev/null +++ b/3rdparty/portaudio/cmake/cmake_uninstall.cmake.in @@ -0,0 +1,21 @@ +if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") +endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + +file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +foreach(file ${files}) + message(STATUS "Uninstalling $ENV{DESTDIR}${file}") + if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + exec_program( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") + endif(NOT "${rm_retval}" STREQUAL 0) + else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File $ENV{DESTDIR}${file} does not exist.") + endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") +endforeach(file) diff --git a/3rdparty/portaudio/cmake/modules/FindASIO.cmake b/3rdparty/portaudio/cmake/modules/FindASIO.cmake new file mode 100644 index 00000000000..d67cf42b929 --- /dev/null +++ b/3rdparty/portaudio/cmake/modules/FindASIO.cmake @@ -0,0 +1,79 @@ +#[=======================================================================[.rst: +FindASIO +-------- + +Finds the ASIO SDK by searching for the SDK ZIP in CMAKE_PREFIX_PATH and +CMAKE_CURRENT_BINARY_DIR. Alternatively, you may manually specify the path of +the SDK ZIP with the ASIO_SDK_ZIP_PATH variable, which can be used for caching +in CI scripts. + +If the ZIP is found, this module extracts it. +The ZIP extraction is skipped if the unzipped SDK is found. + +This module provides an `ASIO::host` IMPORT library target for building host +applications which use ASIO drivers. If you want to build an ASIO driver, this +module may serve as a useful start but you will need to modify it. + +#]=======================================================================] + +if(NOT WIN32) + message(FATAL_ERROR "ASIO is only supported on Windows.") +endif() + +file(GLOB HEADER_FILE + "${CMAKE_CURRENT_BINARY_DIR}/asiosdk*/common/asio.h" + "${CMAKE_PREFIX_PATH}/asiosdk*/common/asio.h" + # The old build systems before PortAudio 19.8 used to look for the ASIO SDK + # in the same parent directory as the source code repository. This is no + # longer advised or documented but kept for backwards compatibility. + "${CMAKE_CURRENT_SOURCE_DIR}/../asiosdk*/common/asio.h" +) +if(NOT EXISTS "${HEADER_FILE}") + # The file(ARCHIVE_EXTRACT) command was added in CMake 3.18, so if using an + # older version of CMake, the user needs to extract it themselves. + if(CMAKE_VERSION VERSION_LESS 3.18) + message(STATUS "ASIO SDK NOT found. Download the ASIO SDK ZIP from " + "https://www.steinberg.net/asiosdk and extract it to " + "${CMAKE_PREFIX_PATH} or ${CMAKE_CURRENT_BINARY_DIR}" + ) + return() + endif() + file(GLOB results + "${ASIO_SDK_ZIP_PATH}" + "${CMAKE_CURRENT_BINARY_DIR}/asiosdk*.zip" + "${CMAKE_PREFIX_PATH}/asiosdk*.zip" + "${CMAKE_CURRENT_SOURCE_DIR}/../asiosdk*.zip" + ) + foreach(f ${results}) + if(EXISTS "${f}") + message(STATUS "Extracting ASIO SDK ZIP archive: ${f}") + file(ARCHIVE_EXTRACT INPUT "${f}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") + endif() + endforeach() + file(GLOB HEADER_FILE "${CMAKE_CURRENT_BINARY_DIR}/asiosdk*/common/asio.h") +endif() + +get_filename_component(HEADER_DIR "${HEADER_FILE}" DIRECTORY) +get_filename_component(ASIO_ROOT "${HEADER_DIR}" DIRECTORY) + +if(ASIO_ROOT) + set(ASIO_FOUND TRUE) + message(STATUS "Found ASIO SDK: ${ASIO_ROOT}") + + if(ASIO_FOUND AND NOT TARGET ASIO::host) + add_library(ASIO::host INTERFACE IMPORTED) + target_sources(ASIO::host INTERFACE + "${ASIO_ROOT}/common/asio.cpp" + "${ASIO_ROOT}/host/asiodrivers.cpp" + "${ASIO_ROOT}/host/pc/asiolist.cpp" + ) + target_include_directories(ASIO::host INTERFACE + "${ASIO_ROOT}/common" + "${ASIO_ROOT}/host" + "${ASIO_ROOT}/host/pc" + ) + target_link_libraries(ASIO::host INTERFACE ole32 uuid) + endif() +else() + message(STATUS "ASIO SDK NOT found") +endif() diff --git a/3rdparty/portaudio/cmake/modules/FindJACK.cmake b/3rdparty/portaudio/cmake/modules/FindJACK.cmake new file mode 100644 index 00000000000..5bf8e4272ff --- /dev/null +++ b/3rdparty/portaudio/cmake/modules/FindJACK.cmake @@ -0,0 +1,67 @@ +#[=======================================================================[.rst: +FindJACK +-------- + +Finds the JACK Audio Connection Kit library. + +Imported Targets +^^^^^^^^^^^^^^^^ + +This module provides the following imported targets, if found: + +``JACK::jack`` + The JACK library + +#]=======================================================================] + +# Prefer finding the libraries from pkgconfig rather than find_library. This is +# required to build with PipeWire's reimplementation of the JACK library. +# +# This also enables using PortAudio with the jack2 port in vcpkg. That only +# builds JackWeakAPI (not the JACK server) which dynamically loads the real +# JACK library and forwards API calls to it. JackWeakAPI requires linking `dl` +# in addition to jack, as specified in the pkgconfig file in vcpkg. +find_package(PkgConfig QUIET) +if(PkgConfig_FOUND) + pkg_check_modules(JACK jack) +else() + find_library(JACK_LINK_LIBRARIES + NAMES jack + DOC "JACK library" + ) + find_path(JACK_INCLUDEDIR + NAMES jack/jack.h + DOC "JACK header" + ) +endif() + +find_package(Regex) +list(APPEND JACK_LINK_LIBRARIES Regex::regex) + +if(NOT CMAKE_USE_PTHREADS_INIT) + # This CMake find module is provided by the pthreads port in vcpkg. + find_package(pthreads) + list(APPEND JACK_LINK_LIBRARIES PThreads4W::PThreads4W) +endif() + +if(CMAKE_USE_PTHREADS_INIT OR TARGET PThreads4W::PThreads4W) + set(PTHREADS_AVAILABLE TRUE) +else() + set(PTHREADS_AVAILABLE FALSE) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + JACK + DEFAULT_MSG + JACK_LINK_LIBRARIES + JACK_INCLUDEDIR + PTHREADS_AVAILABLE + Regex_FOUND +) + +if(JACK_FOUND AND NOT TARGET JACK::jack) + add_library(JACK::jack INTERFACE IMPORTED) + target_link_libraries(JACK::jack INTERFACE "${JACK_LINK_LIBRARIES}" Regex::regex) + target_include_directories(JACK::jack INTERFACE "${JACK_INCLUDEDIR}") +endif() diff --git a/3rdparty/portaudio/cmake/modules/FindOSS.cmake b/3rdparty/portaudio/cmake/modules/FindOSS.cmake new file mode 100644 index 00000000000..eec7dc33789 --- /dev/null +++ b/3rdparty/portaudio/cmake/modules/FindOSS.cmake @@ -0,0 +1,57 @@ +#[=======================================================================[.rst: +FindOSS +-------- + +Finds the Open Sound System include directory. There is no library to link. + +Imported Targets +^^^^^^^^^^^^^^^^ + +This module provides the following imported targets, if found: + +``OSS::oss`` + Target for the OSS header include directory. One of the following + compile definitions is added to the target: + HAVE_SYS_SOUNDCARD_H if the header is sys/soundcard.h + HAVE_LINUX_SOUNDCARD_H if the header is linux/soundcard.h + HAVE_MACHINE_SOUNDCARD_H if the header is machine/soundcard.h + +#]=======================================================================] + +find_path(OSS_INCLUDE_DIR + NAMES sys/soundcard.h + DOC "OSS include directory") +if(OSS_INCLUDE_DIR) + set(OSS_DEFINITIONS HAVE_SYS_SOUNDCARD_H) +else() + find_path(OSS_INCLUDE_DIR + NAMES linux/soundcard.h + DOC "OSS include directory") + if(OSS_INCLUDE_DIR) + set(OSS_DEFINITIONS HAVE_LINUX_SOUNDCARD_H) + else() + find_path(OSS_INCLUDE_DIR + NAMES machine/soundcard.h + DOC "OSS include directory") + if(OSS_INCLUDE_DIR) + set(OSS_DEFINITIONS HAVE_MACHINE_SOUNDCARD_H) + endif() + endif() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + OSS + DEFAULT_MSG + OSS_INCLUDE_DIR + OSS_DEFINITIONS +) + +if(OSS_INCLUDE_DIR AND OSS_DEFINITIONS) + set(OSS_FOUND TRUE) + if(NOT TARGET OSS::oss) + add_library(OSS::oss INTERFACE IMPORTED) + target_include_directories(OSS::oss INTERFACE "${OSS_INCLUDE_DIR}") + target_compile_definitions(OSS::oss INTERFACE "${OSS_DEFINITIONS}") + endif() +endif() diff --git a/3rdparty/portaudio/cmake/modules/FindRegex.cmake b/3rdparty/portaudio/cmake/modules/FindRegex.cmake new file mode 100644 index 00000000000..8793de613c7 --- /dev/null +++ b/3rdparty/portaudio/cmake/modules/FindRegex.cmake @@ -0,0 +1,68 @@ +#[=======================================================================[.rst: +FindRegex +-------- + +Finds an implementation of POSIX regular expressions. It first checks if the +standard regex.h POSIX header is available. If not, it looks for the TRE library. +MinGW does not come with regex.h, so TRE is useful with MinGW. + +Imported Targets +^^^^^^^^^^^^^^^^ + +This module provides the following imported targets, if found: + +``Regex::regex`` + The POSIX regular expression implementation + +#]=======================================================================] + +include(FindPackageHandleStandardArgs) +include(CheckIncludeFile) + +set(CMAKE_REQUIRED_QUIET TRUE) +check_include_file(regex.h REGEX_H) +set(CMAKE_REQUIRED_QUIET FALSE) + +if(REGEX_H) + # No need to add any include directories or link any libraries; + # simply provide a dummy target. + if(NOT TARGET Regex::regex) + add_library(Regex::regex INTERFACE IMPORTED) + endif() + + # check_include_file sets the variable to "1" which looks odd in the output + # of find_package_handle_standard_args, so show the user what was actually found. + set(REGEX_H "POSIX regex.h") + find_package_handle_standard_args( + Regex + DEFAULT_MSG + REGEX_H + ) +else() + # MinGW does not include regex.h but this can be supplied by the TRE library. + find_path(TRE_REGEX_H NAMES tre/regex.h) + if(TRE_REGEX_H) + # The POSIX #include is simply but the tre regex.h is at , + # so add the directory containing tre's headers to the include path. + set(TRE_INCLUDE_DIR "${TRE_REGEX_H}/tre") + endif() + find_library(TRE_LIBRARY NAMES tre) + if(TRE_REGEX_H AND TRE_LIBRARY) + message(STATUS "Found regex.h from TRE") + else() + message(STATUS "regex.h POSIX header NOT found and NOT available from TRE") + endif() + + if(NOT TARGET Regex::regex) + add_library(Regex::regex INTERFACE IMPORTED) + target_include_directories(Regex::regex INTERFACE "${TRE_INCLUDE_DIR}") + target_link_libraries(Regex::regex INTERFACE "${TRE_LIBRARY}") + endif() + + find_package_handle_standard_args( + Regex + DEFAULT_MSG + TRE_INCLUDE_DIR + TRE_LIBRARY + ) +endif() diff --git a/3rdparty/portaudio/cmake/portaudio-2.0.pc.in b/3rdparty/portaudio/cmake/portaudio-2.0.pc.in new file mode 100644 index 00000000000..414be0532be --- /dev/null +++ b/3rdparty/portaudio/cmake/portaudio-2.0.pc.in @@ -0,0 +1,13 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ + +Name: PortAudio +Description: Portable audio I/O +Version: @CMAKE_PROJECT_VERSION@ + +Libs: -L${libdir} -lportaudio +Libs.private: @PKGCONFIG_LDFLAGS_PRIVATE@ +Cflags: -I${includedir} @PKGCONFIG_CFLAGS@ +Requires.private: @PKGCONFIG_REQUIRES_PRIVATE@ diff --git a/3rdparty/portaudio/cmake/portaudio.def.in b/3rdparty/portaudio/cmake/portaudio.def.in new file mode 100644 index 00000000000..7df1e64dadd --- /dev/null +++ b/3rdparty/portaudio/cmake/portaudio.def.in @@ -0,0 +1,67 @@ +; $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 +Pa_GetVersionInfo @35 +@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_GetAudioClient @56 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_UpdateDeviceList @57 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetDeviceCurrentFormat @58 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetDeviceDefaultFormat @59 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetDeviceMixFormat @60 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetDeviceRole @61 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_ThreadPriorityBoost @62 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_ThreadPriorityRevert @63 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetFramesPerHostBuffer @64 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetJackCount @65 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetJackDescription @66 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_SetStreamStateHandler @68 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapiWinrt_SetDefaultDeviceId @67 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapiWinrt_PopulateDeviceList @69 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_GetIMMDevice @70 +@DEF_EXCLUDE_WASAPI_SYMBOLS@PaWasapi_IsLoopback @71 +@DEF_EXCLUDE_WMME_SYMBOLS@PaWinMME_GetStreamInputHandleCount @72 +@DEF_EXCLUDE_WMME_SYMBOLS@PaWinMME_GetStreamInputHandle @73 +@DEF_EXCLUDE_WMME_SYMBOLS@PaWinMME_GetStreamOutputHandleCount @74 +@DEF_EXCLUDE_WMME_SYMBOLS@PaWinMME_GetStreamOutputHandle @75 diff --git a/3rdparty/portaudio/cmake/toolchains/i686-w64-mingw32.cmake b/3rdparty/portaudio/cmake/toolchains/i686-w64-mingw32.cmake new file mode 100644 index 00000000000..2a2c7bfc48c --- /dev/null +++ b/3rdparty/portaudio/cmake/toolchains/i686-w64-mingw32.cmake @@ -0,0 +1,17 @@ +# CMake Toolchain file for cross-compiling PortAudio to i686-w64-mingw32 +# Inspired from: https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/cross_compiling/Mingw +# Example usage: $ cmake -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/i686-w64-mingw32.cmake . +# i686-w64-mingw32 needs to be installed for this to work. On Debian-based +# distributions the package is typically named `mingw-w64`. + +SET(CMAKE_SYSTEM_NAME Windows) + +SET(CMAKE_C_COMPILER i686-w64-mingw32-gcc) +SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) +SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres) + +SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/3rdparty/portaudio/configure b/3rdparty/portaudio/configure index 52314fe277a..311eff23486 100755 --- a/3rdparty/portaudio/configure +++ b/3rdparty/portaudio/configure @@ -723,6 +723,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -746,6 +747,7 @@ ac_subst_files='' ac_user_opts=' enable_option_checking with_alsa +with_audioio with_jack with_oss with_asihpi @@ -821,6 +823,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' @@ -1073,6 +1076,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1210,7 +1222,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1363,6 +1375,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1409,6 +1422,7 @@ Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-alsa Enable support for ALSA [autodetect] + --with-audioio Enable support for Solaris/NetBSD audio [autodetect] --with-jack Enable support for JACK [autodetect] --with-oss Enable support for OSS [autodetect] --with-asihpi Enable support for ASIHPI [autodetect] @@ -2527,6 +2541,14 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu +PAMAC_TEST_PROGRAM=" + /* cdefs.h checks for supported architectures. */ + #include + int main() { + return 0; + } +" + ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then @@ -2676,6 +2698,13 @@ fi +# Check whether --with-audioio was given. +if test "${with_audioio+set}" = set; then : + withval=$with_audioio; with_audioio=$withval +fi + + + # Check whether --with-jack was given. if test "${with_jack+set}" = set; then : withval=$with_jack; with_jack=$withval @@ -15357,6 +15386,21 @@ else have_asihpi=no fi +fi +have_audioio=no +if test "x$with_audioio" != "xno"; then + for ac_header in sys/audioio.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "sys/audioio.h" "ac_cv_header_sys_audioio_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_audioio_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_AUDIOIO_H 1 +_ACEOF + have_audioio=yes +fi + +done + fi have_libossaudio=no have_oss=no @@ -15822,67 +15866,21 @@ case "${host_os}" in $as_echo "#define PA_USE_COREAUDIO 1" >>confdefs.h - CFLAGS="$CFLAGS -I\$(top_srcdir)/src/os/unix -Wno-deprecated -Werror" - LIBS="-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework Carbon" + CFLAGS="$CFLAGS -I\$(top_srcdir)/src/os/unix -Wno-deprecated" + LIBS="-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreFoundation -framework CoreServices" if test "x$enable_mac_universal" = "xyes" ; then - case `xcodebuild -version | sed -n 's/Xcode \(.*\)/\1/p'` in - - 12*|3.0|3.1) - if [ -d /Developer/SDKs/MacOSX10.5.sdk ] ; then - mac_version_min="-mmacosx-version-min=10.3" - mac_sysroot="-isysroot /Developer/SDKs/MacOSX10.5.sdk" - else - mac_version_min="-mmacosx-version-min=10.3" - mac_sysroot="-isysroot /Developer/SDKs/MacOSX10.4u.sdk" - fi - ;; - - *) - if xcodebuild -version -sdk macosx10.5 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.3" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.5 Path`" - elif xcodebuild -version -sdk macosx10.6 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.4" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.6 Path`" - elif xcodebuild -version -sdk macosx10.7 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.4" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.7 Path`" - elif xcodebuild -version -sdk macosx10.8 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.4" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.8 Path`" - elif xcodebuild -version -sdk macosx10.9 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.4" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.9 Path`" - elif xcodebuild -version -sdk macosx10.10 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.4" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.10 Path`" - elif xcodebuild -version -sdk macosx10.11 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.4" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.11 Path`" - elif xcodebuild -version -sdk macosx10.12 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.4" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.12 Path`" - else - as_fn_error $? "Could not find 10.5 to 10.12 SDK." "$LINENO" 5 - fi - esac + mac_version_min="-mmacosx-version-min=10.6" + mac_sysroot="-isysroot $(xcrun --sdk macosx --show-sdk-path)" mac_arches="" - for arch in i386 x86_64 ppc ppc64 + for arch in x86_64 arm64 do save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -arch $arch" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - -int -main () -{ -return 0; - ; - return 0; -} +$PAMAC_TEST_PROGRAM _ACEOF if ac_fn_c_try_compile "$LINENO"; then : @@ -15902,7 +15900,42 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext mac_version="" fi SHARED_FLAGS="$LIBS -dynamiclib $mac_arches $mac_sysroot $mac_version_min" - CFLAGS="-std=c99 $CFLAGS $mac_arches $mac_sysroot $mac_version_min" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -std=c11" >&5 +$as_echo_n "checking whether C compiler accepts -std=c11... " >&6; } +if ${ax_cv_check_cflags___std_c11+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS -std=c11" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ax_cv_check_cflags___std_c11=yes +else + ax_cv_check_cflags___std_c11=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___std_c11" >&5 +$as_echo "$ax_cv_check_cflags___std_c11" >&6; } +if test "x$ax_cv_check_cflags___std_c11" = xyes; then : + CFLAGS="-std=c11 $CFLAGS" +else + CFLAGS="-std=c99 $CFLAGS" +fi + + CFLAGS="$CFLAGS $mac_arches $mac_sysroot $mac_version_min" OTHER_OBJS="src/os/unix/pa_unix_hostapis.o src/os/unix/pa_unix_util.o src/hostapi/coreaudio/pa_mac_core.o src/hostapi/coreaudio/pa_mac_core_utilities.o src/hostapi/coreaudio/pa_mac_core_blocking.o src/common/pa_ringbuffer.o" PADLL="libportaudio.dylib" ;; @@ -15922,6 +15955,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext #VC98="\"/c/Program Files/Microsoft Visual Studio/VC98/Include\"" #CFLAGS="$CFLAGS -I$VC98 -DPA_NO_WMME -DPA_NO_ASIO" CFLAGS="$CFLAGS -I$DXDIR/include -UPA_USE_DS -DPA_USE_DS=1" + INCLUDES="$INCLUDES pa_win_ds.h pa_win_waveformat.h" fi if [ "x$with_asio" = "xyes" ]; then @@ -15930,6 +15964,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext LIBS="${LIBS} -lwinmm -lm -lole32 -luuid" DLL_LIBS="${DLL_LIBS} -lwinmm -lm -lole32 -luuid" CFLAGS="$CFLAGS -ffast-math -fomit-frame-pointer -I\$(top_srcdir)/src/hostapi/asio -I$ASIODIR/host/pc -I$ASIODIR/common -I$ASIODIR/host -UPA_USE_ASIO -DPA_USE_ASIO=1 -DWINDOWS" + INCLUDES="$INCLUDES pa_asio.h" CFLAGS="$CFLAGS -D_WIN32_WINNT=0x0501 -DWINVER=0x0501" @@ -15944,6 +15979,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext #VC98="\"/c/Program Files/Microsoft Visual Studio/VC98/Include\"" #CFLAGS="$CFLAGS -I$VC98 -DPA_NO_WMME -DPA_NO_ASIO" CFLAGS="$CFLAGS -I$DXDIR/include -UPA_USE_WDMKS -DPA_USE_WDMKS=1" + INCLUDES="$INCLUDES pa_win_wdmks.h" fi if [ "x$with_wmme" = "xyes" ]; then @@ -15951,13 +15987,15 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext LIBS="${LIBS} -lwinmm -lm -lole32 -luuid" DLL_LIBS="${DLL_LIBS} -lwinmm" CFLAGS="$CFLAGS -UPA_USE_WMME -DPA_USE_WMME=1" + INCLUDES="$INCLUDES pa_win_wmme.h pa_win_waveformat.h" fi if [ "x$with_wasapi" = "xyes" ]; then add_objects src/hostapi/wasapi/pa_win_wasapi.o src/common/pa_ringbuffer.o src/os/win/pa_win_hostapis.o src/os/win/pa_win_util.o src/os/win/pa_win_coinitialize.o src/os/win/pa_win_waveformat.o LIBS="${LIBS} -lwinmm -lm -lole32 -luuid" DLL_LIBS="${DLL_LIBS} -lwinmm -lole32" - CFLAGS="$CFLAGS -I\$(top_srcdir)/src/hostapi/wasapi/mingw-include -UPA_USE_WASAPI -DPA_USE_WASAPI=1" + CFLAGS="$CFLAGS -UPA_USE_WASAPI -DPA_USE_WASAPI=1" + INCLUDES="$INCLUDES pa_win_wasapi.h pa_win_waveformat.h" fi ;; @@ -16185,6 +16223,12 @@ fi fi + if [ "$have_audioio" = "yes" ] && [ "$with_audioio" != "no" ] ; then + OTHER_OBJS="$OTHER_OBJS src/hostapi/audioio/pa_unix_audioio.o" + $as_echo "#define PA_USE_AUDIOIO 1" >>confdefs.h + + fi + if [ "$have_jack" = "yes" ] && [ "$with_jack" != "no" ] ; then DLL_LIBS="$DLL_LIBS $JACK_LIBS" CFLAGS="$CFLAGS $JACK_CFLAGS" @@ -18816,10 +18860,12 @@ $as_echo " ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: + AudioIO ..................... $have_audioio OSS ......................... $have_oss JACK ........................ $have_jack " >&5 $as_echo " + AudioIO ..................... $have_audioio OSS ......................... $have_oss JACK ........................ $have_jack " >&6; } diff --git a/3rdparty/portaudio/configure.in b/3rdparty/portaudio/configure.in index 13816fb7a34..d3f4fe19839 100644 --- a/3rdparty/portaudio/configure.in +++ b/3rdparty/portaudio/configure.in @@ -11,6 +11,15 @@ dnl Init autoconf and make sure configure is being called dnl from the right directory AC_INIT([include/portaudio.h]) +dnl This is is for testing compilation on Mac OS +PAMAC_TEST_PROGRAM=" + /* cdefs.h checks for supported architectures. */ + #include + int main() { + return 0; + } +" + dnl Define build, build_cpu, build_vendor, build_os AC_CANONICAL_BUILD dnl Define host, host_cpu, host_vendor, host_os @@ -24,6 +33,10 @@ AC_ARG_WITH(alsa, AS_HELP_STRING([--with-alsa], [Enable support for ALSA @<:@autodetect@:>@]), [with_alsa=$withval]) +AC_ARG_WITH(audioio, + AS_HELP_STRING([--with-audioio], [Enable support for Solaris/NetBSD audio @<:@autodetect@:>@]), + [with_audioio=$withval]) + AC_ARG_WITH(jack, AS_HELP_STRING([--with-jack], [Enable support for JACK @<:@autodetect@:>@]), [with_jack=$withval]) @@ -124,6 +137,10 @@ have_asihpi=no if test "x$with_asihpi" != "xno"; then AC_CHECK_LIB(hpi, HPI_SubSysCreate, have_asihpi=yes, have_asihpi=no, -lm) fi +have_audioio=no +if test "x$with_audioio" != "xno"; then + AC_CHECK_HEADERS([sys/audioio.h], [have_audioio=yes]) +fi have_libossaudio=no have_oss=no if test "x$with_oss" != "xno"; then @@ -204,73 +221,22 @@ case "${host_os}" in AC_DEFINE(PA_USE_COREAUDIO,1) - CFLAGS="$CFLAGS -I\$(top_srcdir)/src/os/unix -Wno-deprecated -Werror" - LIBS="-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework Carbon" + CFLAGS="$CFLAGS -I\$(top_srcdir)/src/os/unix -Wno-deprecated" + LIBS="-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreFoundation -framework CoreServices" if test "x$enable_mac_universal" = "xyes" ; then - case `xcodebuild -version | sed -n 's/Xcode \(.*\)/\1/p'` in - - [12]*|3.0|3.1) - dnl In pre-3.2 versions of Xcode, xcodebuild doesn't - dnl support -sdk, so we can't use that to look for - dnl SDKs. However, in those versions of Xcode, the - dnl SDKs are under /Developer/SDKs, so we can just look - dnl there. Also, we assume they had no SDKs later - dnl than 10.5, as 3.2 was the version that came with - dnl 10.6, at least if the Wikipedia page for Xcode - dnl is to be believed. - if [[ -d /Developer/SDKs/MacOSX10.5.sdk ]] ; then - mac_version_min="-mmacosx-version-min=10.3" - mac_sysroot="-isysroot /Developer/SDKs/MacOSX10.5.sdk" - else - mac_version_min="-mmacosx-version-min=10.3" - mac_sysroot="-isysroot /Developer/SDKs/MacOSX10.4u.sdk" - fi - ;; - - *) - dnl In 3.2 and later, xcodebuild supports -sdk, and, in - dnl 4.3 and later, the SDKs aren't under /Developer/SDKs - dnl as there *is* no /Developer, so we use -sdk to check - dnl what SDKs are available and to get the full path of - dnl the SDKs. - if xcodebuild -version -sdk macosx10.5 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.3" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.5 Path`" - elif xcodebuild -version -sdk macosx10.6 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.4" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.6 Path`" - elif xcodebuild -version -sdk macosx10.7 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.4" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.7 Path`" - elif xcodebuild -version -sdk macosx10.8 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.4" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.8 Path`" - elif xcodebuild -version -sdk macosx10.9 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.4" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.9 Path`" - elif xcodebuild -version -sdk macosx10.10 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.4" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.10 Path`" - elif xcodebuild -version -sdk macosx10.11 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.4" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.11 Path`" - elif xcodebuild -version -sdk macosx10.12 Path >/dev/null 2>&1 ; then - mac_version_min="-mmacosx-version-min=10.4" - mac_sysroot="-isysroot `xcodebuild -version -sdk macosx10.12 Path`" - else - AC_MSG_ERROR([Could not find 10.5 to 10.12 SDK.]) - fi - esac + mac_version_min="-mmacosx-version-min=10.6" + mac_sysroot="-isysroot $(xcrun --sdk macosx --show-sdk-path)" dnl Pick which architectures to build for based on what - dnl the compiler supports. + dnl the compiler and SDK supports. mac_arches="" - for arch in i386 x86_64 ppc ppc64 + for arch in x86_64 arm64 do save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -arch $arch" - AC_TRY_COMPILE([], [return 0;], + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE([$PAMAC_TEST_PROGRAM])], [ if [[ -z "$mac_arches" ]] ; then mac_arches="-arch $arch" @@ -286,7 +252,8 @@ case "${host_os}" in mac_version="" fi SHARED_FLAGS="$LIBS -dynamiclib $mac_arches $mac_sysroot $mac_version_min" - CFLAGS="-std=c99 $CFLAGS $mac_arches $mac_sysroot $mac_version_min" + AX_CHECK_COMPILE_FLAG([-std=c11], [CFLAGS="-std=c11 $CFLAGS"], [CFLAGS="-std=c99 $CFLAGS"]) + CFLAGS="$CFLAGS $mac_arches $mac_sysroot $mac_version_min" OTHER_OBJS="src/os/unix/pa_unix_hostapis.o src/os/unix/pa_unix_util.o src/hostapi/coreaudio/pa_mac_core.o src/hostapi/coreaudio/pa_mac_core_utilities.o src/hostapi/coreaudio/pa_mac_core_blocking.o src/common/pa_ringbuffer.o" PADLL="libportaudio.dylib" ;; @@ -307,6 +274,7 @@ case "${host_os}" in #VC98="\"/c/Program Files/Microsoft Visual Studio/VC98/Include\"" #CFLAGS="$CFLAGS -I$VC98 -DPA_NO_WMME -DPA_NO_ASIO" CFLAGS="$CFLAGS -I$DXDIR/include -UPA_USE_DS -DPA_USE_DS=1" + INCLUDES="$INCLUDES pa_win_ds.h pa_win_waveformat.h" fi if [[ "x$with_asio" = "xyes" ]]; then @@ -315,13 +283,14 @@ case "${host_os}" in LIBS="${LIBS} -lwinmm -lm -lole32 -luuid" DLL_LIBS="${DLL_LIBS} -lwinmm -lm -lole32 -luuid" CFLAGS="$CFLAGS -ffast-math -fomit-frame-pointer -I\$(top_srcdir)/src/hostapi/asio -I$ASIODIR/host/pc -I$ASIODIR/common -I$ASIODIR/host -UPA_USE_ASIO -DPA_USE_ASIO=1 -DWINDOWS" + INCLUDES="$INCLUDES pa_asio.h" - dnl Setting the windows version flags below resolves a conflict between Interlocked* - dnl definitions in mingw winbase.h and Interlocked* hacks in ASIO SDK combase.h + dnl Setting the windows version flags below resolves a conflict between Interlocked* + dnl definitions in mingw winbase.h and Interlocked* hacks in ASIO SDK combase.h dnl combase.h is included by asiodrvr.h - dnl PortAudio does not actually require Win XP (winver 501) APIs + dnl PortAudio does not actually require Win XP (winver 501) APIs CFLAGS="$CFLAGS -D_WIN32_WINNT=0x0501 -DWINVER=0x0501" - + CXXFLAGS="$CFLAGS" fi @@ -333,6 +302,7 @@ case "${host_os}" in #VC98="\"/c/Program Files/Microsoft Visual Studio/VC98/Include\"" #CFLAGS="$CFLAGS -I$VC98 -DPA_NO_WMME -DPA_NO_ASIO" CFLAGS="$CFLAGS -I$DXDIR/include -UPA_USE_WDMKS -DPA_USE_WDMKS=1" + INCLUDES="$INCLUDES pa_win_wdmks.h" fi if [[ "x$with_wmme" = "xyes" ]]; then @@ -340,13 +310,15 @@ case "${host_os}" in LIBS="${LIBS} -lwinmm -lm -lole32 -luuid" DLL_LIBS="${DLL_LIBS} -lwinmm" CFLAGS="$CFLAGS -UPA_USE_WMME -DPA_USE_WMME=1" + INCLUDES="$INCLUDES pa_win_wmme.h pa_win_waveformat.h" fi if [[ "x$with_wasapi" = "xyes" ]]; then add_objects src/hostapi/wasapi/pa_win_wasapi.o src/common/pa_ringbuffer.o src/os/win/pa_win_hostapis.o src/os/win/pa_win_util.o src/os/win/pa_win_coinitialize.o src/os/win/pa_win_waveformat.o LIBS="${LIBS} -lwinmm -lm -lole32 -luuid" DLL_LIBS="${DLL_LIBS} -lwinmm -lole32" - CFLAGS="$CFLAGS -I\$(top_srcdir)/src/hostapi/wasapi/mingw-include -UPA_USE_WASAPI -DPA_USE_WASAPI=1" + CFLAGS="$CFLAGS -UPA_USE_WASAPI -DPA_USE_WASAPI=1" + INCLUDES="$INCLUDES pa_win_wasapi.h pa_win_waveformat.h" fi ;; @@ -380,7 +352,7 @@ case "${host_os}" in dnl The _REENTRANT option for pthread safety. Perhaps not necessary but it 'll do no harm. dnl THREAD_CFLAGS="-D_REENTRANT" - + OTHER_OBJS="pa_sgi/pa_sgi.o src/os/unix/pa_unix_hostapis.o src/os/unix/pa_unix_util.o" dnl SGI books say -lpthread should be the last of the libs mentioned. @@ -394,7 +366,7 @@ case "${host_os}" in dnl Unix configuration CFLAGS="$CFLAGS -I\$(top_srcdir)/src/os/unix" - + AC_CHECK_LIB(pthread, pthread_create,[have_pthread="yes"], AC_MSG_ERROR([libpthread not found!])) @@ -406,6 +378,11 @@ case "${host_os}" in AC_DEFINE(PA_USE_ALSA,1) fi + if [[ "$have_audioio" = "yes" ] && [ "$with_audioio" != "no" ]] ; then + OTHER_OBJS="$OTHER_OBJS src/hostapi/audioio/pa_unix_audioio.o" + AC_DEFINE(PA_USE_AUDIOIO,1) + fi + if [[ "$have_jack" = "yes" ] && [ "$with_jack" != "no" ]] ; then DLL_LIBS="$DLL_LIBS $JACK_LIBS" CFLAGS="$CFLAGS $JACK_CFLAGS" @@ -509,6 +486,7 @@ case "$target_os" in ;; *) AC_MSG_RESULT([ + AudioIO ..................... $have_audioio OSS ......................... $have_oss JACK ........................ $have_jack ]) diff --git a/3rdparty/portaudio/doc/src/api_overview.dox b/3rdparty/portaudio/doc/src/api_overview.dox index 98a0dbdddbc..e5704ce737d 100644 --- a/3rdparty/portaudio/doc/src/api_overview.dox +++ b/3rdparty/portaudio/doc/src/api_overview.dox @@ -112,7 +112,7 @@ Many of the tests in the /tests directory of the PortAudio distribution implemen @subsection read_write_io_method The Read/Write I/O Method -As an alternative to the callback I/O method, PortAudio provides a synchronous read/write interface for acquiring and playing audio. This can be useful for applications that don't require the lowest possibly latency, or don't warrant the increased complexity of synchronising with an asynchronous callback funciton. This I/O method is also useful when calling PortAudio from programming languages that don't support asynchronous callbacks. +As an alternative to the callback I/O method, PortAudio provides a synchronous read/write interface for acquiring and playing audio. This can be useful for applications that don't require the lowest possibly latency, or don't warrant the increased complexity of synchronising with an asynchronous callback function. This I/O method is also useful when calling PortAudio from programming languages that don't support asynchronous callbacks. To open a Stream in read/write mode you pass a NULL stream callback function pointer to Pa_OpenStream(). diff --git a/3rdparty/portaudio/doc/src/mainpage.dox b/3rdparty/portaudio/doc/src/mainpage.dox index 7a54d320400..53e0060ad1b 100644 --- a/3rdparty/portaudio/doc/src/mainpage.dox +++ b/3rdparty/portaudio/doc/src/mainpage.dox @@ -34,9 +34,9 @@ Documentation for non-portable platform-specific host API extensions - The PortAudio website -- Our mailing list for users and developers
+- Our mailing list for users and developers
-- The PortAudio wiki +- The PortAudio wiki @section developer_resources Developer Resources @@ -44,18 +44,20 @@ Documentation for non-portable platform-specific host API extensions - @ref srcguide @endif -- Our wiki and issue tracking system +- Our repository on GitHub -- Developer guidelines +- Developer guidelines -- Implementation style guidelines - -If you're interested in helping out with PortAudio development we're more than happy for you to be involved. Just drop by the PortAudio mailing list and ask how you can help. Or check out the starter tickets. +- Implementation style guidelines +If you're interested in helping out with PortAudio development we're more than happy for you to be involved. +Just drop by the PortAudio mailing list and ask how you can help. +Or check out these +recommended starter issues. @section older_api_versions Older API Versions This documentation covers the current API version: PortAudio V19, API version 2.0. API 2.0 differs in a number of ways from previous versions (most often encountered in PortAudio V18), please consult the enhancement proposals for details of what was added/changed for V19: http://www.portaudio.com/docs/proposals/index.html -*/ \ No newline at end of file +*/ diff --git a/3rdparty/portaudio/doc/src/tutorial/compile_cmake.dox b/3rdparty/portaudio/doc/src/tutorial/compile_cmake.dox index ddf5eae610d..8db400e7686 100644 --- a/3rdparty/portaudio/doc/src/tutorial/compile_cmake.dox +++ b/3rdparty/portaudio/doc/src/tutorial/compile_cmake.dox @@ -1,29 +1,57 @@ -/** @page compile_cmake Creating MSVC Build Files via CMake +/** @page compile_cmake PortAudio on Windows, OS X or Linux via. CMake @ingroup tutorial -This is a simple "How-to" for creating build files for Microsoft Visual C++ via CMake and the CMakeLists.txt file +@section cmake_building Building PortAudio stand-alone on Windows, OS X or Linux -1. Install CMake if you haven't got it already ([http://www.cmake.org], minimum version required is 2.8). +CMake can be used to generate Visual Studio solutions on Windows, Makefiles (on Linux and OS X) and build metadata for other build systems for PortAudio. You should obtain a recent version of CMake from [http://www.cmake.org] if you do not have one already. If you are unfamiliar with CMake, this section will provide some information on using CMake to build PortAudio. -2. If you want ASIO support you need to D/L the ASIO2 SDK from Steinberg, and place it according to \ref compile_windows_asio_msvc +On Linux, CMake serves a very similar purpose to an autotools "configure" script - except it can generate build metadata apart from Makefiles. The equivalent of the following on POSIX'y systems: -3. Run the CMake GUI application and browse to source files directory and build directory: - a. The source files directory ("Where is the source code") is where the portaudio CMakeLists.txt file is located. - b. The build directory ("Where to build the binaries") is pretty much anywhere you like. A common practice though is to have the build directory located outside the - source files tree (a so called "out-of-source build") + build_path> {portaudio path}/configure --prefix=/install_location + build_path> make + build_path> make install -4. Click Configure. This will prompt you to select which build files to generate. Note Only Microsoft Visual C++ build files currently supported! +Would be: -5. In the CMake option list, enable the PORTAUDIO_xxx options you need, then click Configure again (Note that after this there are no options marked with red color) + build_path> cmake {portaudio path} -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/install_location + build_path> make + build_path> make install -6. Click Generate and you'll now (hopefully) have your VS build files in your previously defined build directory. +The "-G" option specifies the type of build metadata which will be generated. You can obtain a list of supported build metadata formats by invoking (on any platform): -Both ASIO and DirectX SDK are automatically searched for by the CMake script, so if you have DirectX SDK installed and have placed the ASIO2 SDK according to point 2 above, you should be able to build portaudio with !DirectSound and ASIO support. + cmake -G -Should you later on decide to change a portaudio option, just jump in at step 5 above (MSVC will then prompt you to reload projects/solutions/workspace) +"make install" should install the same set of files that are installed using the usual configure script included with PortAudio along with a few extra files (similar to pkg-config metadata files) which make it easier for other CMake projects to use the installed libraries. ---- Robert Bielik +On Windows, you can use CMake to generate Visual Studio project files which can be used to create the PortAudio libraries. The following serves as an example (and should be done from a directory outside the PortAudio tree) which will create Visual Studio 2015 project files targeting a 64-bit build: -Back to the Tutorial: \ref tutorial_start + C:\PABUILD> cmake {portaudio path} -G "Visual Studio 14 2015 Win64" + +After executing the above, you can either open the generated solution with Visual Studio or use CMake to invoke the build process. The following shows an example of how to build a release configuration (assuming the above command was executed previously in the same directory): + + C:\PABUILD> cmake --build . --config Release + +If you want ASIO support you need to obtain the ASIO2 SDK from Steinberg and place it according to \ref compile_windows_asio_msvc. Both ASIO and the DirectX SDK are automatically searched for by the CMake script - if they are found, they will be enabled by default. + +@section cmake_using Using PortAudio in your CMake project + +PortAudio defines the following CMake targets: + + - "portaudio_static" for a static library and + - "portaudio" for a dynamic library + +If you installed PortAudio as described above in \ref cmake_building and the install prefix you used (CMAKE_INSTALL_PREFIX) is in your system PATH or CMAKE_MODULE_PATH CMake variable, you should be able to use: + + find_package(portaudio) + +To define the "portaudio_static" and "portaudio" targets in your CMake project. + +If you do not want to install portaudio into your system but would rather just have it get built as part of your own project (which may be particularly convenient on Windows), you may also use: + + add_subdirectory("path to PortAudio location" "some binary directory" EXCLUDE_FROM_ALL) + +EXCLUDE_FROM_ALL is not strictly necessary, but will ensure that targets which you don't use in your project won't get built. + +Back to \ref tutorial_start */ \ No newline at end of file diff --git a/3rdparty/portaudio/doc/src/tutorial/compile_linux.dox b/3rdparty/portaudio/doc/src/tutorial/compile_linux.dox index e227d759a36..2c993ca83ef 100644 --- a/3rdparty/portaudio/doc/src/tutorial/compile_linux.dox +++ b/3rdparty/portaudio/doc/src/tutorial/compile_linux.dox @@ -47,7 +47,7 @@ On some systems you may need to use: cp /usr/local/lib/libportaudio.a /YOUR/PROJECT/DIR @endcode -You may also need to copy portaudio.h, located in the include/ directory of PortAudio into your project. Note that you will usually need to link with the approriate libraries that you used, such as ALSA and JACK, as well as with librt and libpthread. For example: +You may also need to copy portaudio.h, located in the include/ directory of PortAudio into your project. Note that you will usually need to link with the appropriate libraries that you used, such as ALSA and JACK, as well as with librt and libpthread. For example: @code gcc main.c libportaudio.a -lrt -lm -lasound -ljack -pthread -o YOUR_BINARY diff --git a/3rdparty/portaudio/doc/src/tutorial/compile_mac_coreaudio.dox b/3rdparty/portaudio/doc/src/tutorial/compile_mac_coreaudio.dox index e16ce33dbd0..3f4de903786 100644 --- a/3rdparty/portaudio/doc/src/tutorial/compile_mac_coreaudio.dox +++ b/3rdparty/portaudio/doc/src/tutorial/compile_mac_coreaudio.dox @@ -3,11 +3,11 @@ @section comp_mac_ca_1 Requirements -* OS X 10.4 or later. PortAudio v19 currently only compiles and runs on OS X version 10.4 or later. Because of its heavy reliance on memory barriers, it's not clear how easy it would be to back-port PortAudio to OS X version 10.3. Leopard support requires the 2007 snapshot or later. +* OS X 10.6 or later. PortAudio v19.7 currently only compiles and runs on OS X version 10.6 or later. * Apple's Xcode and its related tools installed in the default location. There is no Xcode project for PortAudio. -* Mac 10.4 SDK. Look for "/Developer/SDKs/MacOSX10.4u.sdk" folder on your system. It may be installed with XCode. If not then you can download it from Apple Developer Connection. http://connect.apple.com/ +* Mac 10.6 SDK. Look for "/Developer/SDKs/MacOSX10.6.sdk" folder on your system. It may be installed with XCode. If not then you can download it from Apple Developer Connection. http://connect.apple.com/ @section comp_mac_ca_2 Building @@ -29,7 +29,7 @@ There are a variety of other options for building PortAudio. The default describ @subsection comp_mac_ca_3.1 Building Non-Universal Libraries -By default, PortAudio is built as a universal binary. This includes 64-bit versions if you are compiling on 10.5, Leopard. If you want a "thin", or single architecture library, you have two options: +By default, PortAudio is built as a universal binary. This includes 64-bit versions if you are compiling on 10.6, Snow Leopard. If you want a "thin", or single architecture library, you have two options: * build a non-universal library using configure options. * use lipo(1) on whatever part of the library you plan to use. @@ -44,11 +44,11 @@ To build a non-universal library for the host architecture, simply use the -- ./configure --disable-mac-universal && make @endcode -The --disable-mac-universal option may also be used in conjunction with environment variables to give you more control over the universal binary build process. For example, to build a universal binary for the i386 and ppc architectures using the 10.4u sdk (which is the default on 10.4, but not 10.5), you might specify this configure command line: +The --disable-mac-universal option may also be used in conjunction with environment variables to give you more control over the universal binary build process. For example, to build a universal binary for the i386 and ppc architectures using the 10.6 sdk, you might specify this configure command line: @code - CFLAGS="-O2 -g -Wall -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.3" \ - LDFLAGS="-arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.3" \ + CFLAGS="-O2 -g -Wall -arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.6.sdk -mmacosx-version-min=10.6" \ + LDFLAGS="-arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.6.sdk -mmacosx-version-min=10.6" \ ./configure --disable-mac-universal --disable-dependency-tracking @endcode @@ -99,7 +99,7 @@ You will need to add the following frameworks to your XCode project: - AudioToolbox.framework - AudioUnit.framework - CoreServices.framework - - Carbon.framework + - CoreFoundation.framework @section comp_mac_ca_5 Using the Library in Other Projects diff --git a/3rdparty/portaudio/doc/src/tutorial/compile_windows.dox b/3rdparty/portaudio/doc/src/tutorial/compile_windows.dox index 22589398489..bcb6eccf31e 100644 --- a/3rdparty/portaudio/doc/src/tutorial/compile_windows.dox +++ b/3rdparty/portaudio/doc/src/tutorial/compile_windows.dox @@ -1,17 +1,19 @@ /** @page compile_windows Building PortAudio for Windows using Microsoft Visual Studio @ingroup tutorial +NOTE:This page is for building PortAudio using the legacy MSVC project files located in the msvc// directory. You can also use the cmake build system. + Below is a list of steps to build PortAudio into a dll and lib file. The resulting dll file may contain all five current win32 PortAudio APIs: MME, DirectSound, WASAPI, WDM/KS and ASIO, depending on the preprocessor definitions set in step 9 below. PortAudio can be compiled using Visual C++ Express Edition which is available free from Microsoft. If you do not already have a C++ development environment, simply download and install. These instructions have been observed to succeed using Visual Studio 2010 as well. 1) Building PortAudio with DirectSound support requires the files dsound.h and dsconf.h. Download and install the DirectX SDK from http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=3021d52b-514e-41d3-ad02-438a3ba730ba to obtain these files. If you installed the DirectX SDK then the DirectSound libraries and header files should be found automatically by Visual Studio/Visual C++. If you get an error saying dsound.h or dsconf.h is missing, you will need to add an extra include path to the Visual Studio project file referencing the DirectX includes directory. -2) For ASIO support, download the ASIO SDK from Steinberg at http://www.steinberg.net/en/company/developer.html . The SDK is free, but you will need to set up a developer account with Steinberg. To use the Visual Studio projects mentioned below, copy the entire ASIOSDK2 folder into src\\hostapi\\asio\\. Rename it from ASIOSDK2 to ASIOSDK. To build without ASIO (or other host API) see the "Building without ASIO support" section below. +2) To build without ASIO (or other host API) see the "Building without ASIO support" section below. To build with ASIO support, download the ASIO SDK from Steinberg at http://www.steinberg.net/en/company/developer.html . The SDK is free, but you will need to set up a developer account with Steinberg. To use the Visual Studio projects mentioned below, copy the entire ASIOSDK2 folder into src\\hostapi\\asio\\. Rename it from ASIOSDK2 to ASIOSDK. Note: There's an array deletion bug in some versions of the ASIO SDK on Windows. To work around this issue you will need to patch the ASIO SDK. Please see src/host/asio/ASIO-README.txt for the fix. 3) If you have Visual Studio 6.0, 7.0(VC.NET/2001) or 7.1(VC.2003), open portaudio.dsp and convert if needed. -4) If you have Visual Studio 2005, Visual C++ 2008 Express Edition or Visual Studio 2010, open the portaudio.sln file located in build\\msvc\\. Doing so will open Visual Studio or Visual C++. Click "Finish" if a conversion wizard appears. The sln file contains four configurations: Win32 and Win64 in both Release and Debug variants. +4) If you have Visual Studio 2005, Visual C++ 2008 Express Edition or Visual Studio 2010, open the portaudio.sln file located in msvc\\. Doing so will open Visual Studio or Visual C++. Click "Finish" if a conversion wizard appears. The sln file contains four configurations: Win32 and Win64 in both Release and Debug variants. @section comp_win1 For Visual Studio 2005, Visual C++ 2008 Express Edition or Visual Studio 2010 @@ -58,7 +60,7 @@ For each of these, the value of 0 indicates that support for this API should not As when setting Preprocessor definitions, building is a per-configuration per-platform process. Follow these instructions for each configuration/platform combination that you're interested in. -10) From the Build menu click Build -> Build solution. For 32-bit compilations, the dll file created by this process (portaudio_x86.dll) can be found in the directory build\\msvc\\Win32\\Release. For 64-bit compilations, the dll file is called portaudio_x64.dll, and is found in the directory build\\msvc\\x64\\Release. +10) From the Build menu click Build -> Build solution. For 32-bit compilations, the dll file created by this process (portaudio_x86.dll) can be found in the directory msvc\\Win32\\Release. For 64-bit compilations, the dll file is called portaudio_x64.dll, and is found in the directory msvc\\x64\\Release. 11) Now, any project that requires portaudio can be linked with portaudio_x86.lib (or _x64) and include the relevant headers (portaudio.h, and/or pa_asio.h , pa_x86_plain_converters.h) You may want to add/remove some DLL entry points. At the time of writing the following 6 entries are not part of the official PortAudio API defined in portaudio.h: @@ -94,6 +96,17 @@ Project Properties -> Configuration Properties -> C/C++ -> Preprocessor -> Prepr 4) Remove PaAsio_* entry points from portaudio.def +@section comp_win5 List of Windows audio APIs + +WASAPI: recommended by Microsoft. Supported since Windows Vista (includes 7/8/10+). + +ASIO: Low latency API intended for pro audio users; this requires the user to install ASIO drivers. + +WMME, DirectSound: Legacy APIs for greater backward compatibility + +WDM/KS: Low level direct-to-driver API. + + ----- David Viens, davidv@plogue.com diff --git a/3rdparty/portaudio/doc/src/tutorial/compile_windows_asio_msvc.dox b/3rdparty/portaudio/doc/src/tutorial/compile_windows_asio_msvc.dox index cf3a0e59474..858071fa510 100644 --- a/3rdparty/portaudio/doc/src/tutorial/compile_windows_asio_msvc.dox +++ b/3rdparty/portaudio/doc/src/tutorial/compile_windows_asio_msvc.dox @@ -3,6 +3,8 @@ @section comp_win_asiomsvc1 Portaudio Windows ASIO with MSVC +NOTE:This page is for building PortAudio using the legacy MSVC project files located in the msvc// directory. You can also use the cmake build system. + This tutorial describes how to build PortAudio with ASIO support using MSVC *from scratch*, without an existing Visual Studio project. For instructions for building PortAudio (including ASIO support) using the bundled Visual Studio project file see the compiling instructions for \ref compile_windows. ASIO is a low latency audio API from Steinberg. To compile an ASIO @@ -87,6 +89,8 @@ You'll need to make sure the relative paths are correct for the particular direc Some source code in the ASIO SDK is not compatible with the Win32 API UNICODE mode (The ASIO SDK expects the non-Unicode Win32 API). Therefore you need to make sure your project is set to not use Unicode. You do this by setting the project Character Set to "Use Multi-Byte Character Set" (NOT "Use Unicode Character Set"). In VS2010 the Character Set option can be found at Configuration Properties > General > Character Set. (An alternative to setting the project to non-Unicode is to patch asiolist.cpp to work when UNICODE is defined: put #undef UNICODE at the top of the file before windows.h is included.) +Note: There's an array deletion bug in some versions of the ASIO SDK on Windows. To work around this issue you will need to patch the ASIO SDK. Please see src/host/asio/ASIO-README.txt for the fix. + You should now be able to build any of the test executables in the portaudio\\examples directory. We suggest that you start with paex_saw.c because it's one of the simplest example files. diff --git a/3rdparty/portaudio/doc/src/tutorial/compile_windows_mingw-w64.dox b/3rdparty/portaudio/doc/src/tutorial/compile_windows_mingw-w64.dox new file mode 100644 index 00000000000..6328c59130a --- /dev/null +++ b/3rdparty/portaudio/doc/src/tutorial/compile_windows_mingw-w64.dox @@ -0,0 +1,44 @@ +/** @page compile_windows_mingw-w64 Building PortAudio for Windows with MinGW-w64 +@ingroup tutorial + +@section comp_mingw-w64_1 PortAudio for Windows with MinGW-w64 + +MinGW-w64 is a port of Linux toolchains (gcc, clang) to Windows. It comes packaged with Msys2 in its preferred configuration. Msys2 provides a Linux environment and the package manager pacman. +Install MinGW-w64 from https://www.msys2.org/. Follow the instructions on this page. + +Brief excursion: there are many toolchain variants in Msys2, and you must use the same toolchain to compile all projects together. In this tutorial, we will use the msvcrt-gcc toolchain, simply because it's already present on all Windows versions. Readers may eventually want to switch to the ucrt-gcc toolchain later, for their Windows 10+ builds, although there is hardly any benefit to doing so. A list of available toolchains is at https://www.msys2.org/docs/environments/. + +In addition, you have a choice of Windows audio APIs; see the bottom of \ref compile_windows for a list. + +You can either use msys2's precompiled PortAudio or compile PortAudio yourself. To install msys2's precompiled PortAudio, see the next section. To compile PortAudio on your own, skip to the next next section. + +@section comp_mingw-w64_2 Pre-compiled package + +Open your msys2 shell and run "pacman -S mingw-w64-x86_64-portaudio". This will get you a default build of PortAudio. I believe it comes with DirectSound, WASAPI, WD/MKS, WD/MKS_DEVICE_INFO, and WMME. Note the "-x86_64" in the middle of the package name. When you install msys2 packages, you specify the toolchain name in the middle, and "-x86_64" chooses the msvcrt-gcc toolchain. + +@section comp_mingw-w64_3 Compiling from scratch + +We will build with WASAPI only, with no fallback APIs, simply as an example. In the msys2 shell, navigate into your folder of PortAudio. Run: + +@code +pacman -S mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja +mkdir build +cd build +cmake -G Ninja .. -DCMAKE_BUILD_TYPE=Release -DPA_USE_DS=0 -DPA_USE_WDMKS=0 -DPA_USE_WDMKS_DEVICE_INFO=0 -DPA_USE_WMME=0 +cmake --build . +@endcode + +To test if it is working, you can run the sawtooth example (warning, it is very loud!): + +@code +gcc ../examples/paex_saw.c -I../src/common -lportaudio +./a.exe +@endcode + +You can enable the desired fallback APIs again by deleting the terms like "-DPA_USE_WMME=0" in the cmake command. When releasing your application to the public, make sure to copy libportaudio.dll (in the build folder) into your own application's folder. (You'll also need to ship a copy of MinGW-w64's various shared libraries; you can figure out which ones using Microsoft's Process Explorer, and seeing which dlls are accessed from your msys64 folder.) + +Or, compile statically to avoid the issue of dll copies. + +Back to the Tutorial: \ref tutorial_start + +*/ diff --git a/3rdparty/portaudio/doc/src/tutorial/compile_windows_mingw.dox b/3rdparty/portaudio/doc/src/tutorial/compile_windows_mingw.dox index d521b7b8088..26d0a17b1ec 100644 --- a/3rdparty/portaudio/doc/src/tutorial/compile_windows_mingw.dox +++ b/3rdparty/portaudio/doc/src/tutorial/compile_windows_mingw.dox @@ -3,7 +3,11 @@ @section comp_mingw1 Portaudio for Windows With MinGW -This document contains old or out-of-date information. Please see a draft of new MinGW information on our Wiki: PortAudio Wiki: Notes about building PortAudio with MinGW +This document contains old or out-of-date information. Please see +a draft of new MinGW information on our +Wiki: +PortAudio Wiki: Notes about building PortAudio with MinGW +If you are new to MinGW, consider MinGW-64: \ref compile_windows_mingw-w64. It is a newer project. = MinGW/MSYS = @@ -50,4 +54,4 @@ To update your copy or check out a fresh copy of the source Back to the Tutorial: \ref tutorial_start -*/ \ No newline at end of file +*/ diff --git a/3rdparty/portaudio/doc/src/tutorial/start_stop_abort.dox b/3rdparty/portaudio/doc/src/tutorial/start_stop_abort.dox index 6d4f777523d..0ddb4605bd8 100644 --- a/3rdparty/portaudio/doc/src/tutorial/start_stop_abort.dox +++ b/3rdparty/portaudio/doc/src/tutorial/start_stop_abort.dox @@ -10,7 +10,7 @@ PortAudio will not start playing back audio until you start the stream. After ca if( err != paNoError ) goto error; @endcode -You can communicate with your callback routine through the data structure you passed in on the open call, or through global variables, or using other interprocess communication techniques, but please be aware that your callback function may be called at interrupt time when your foreground process is least expecting it. So avoid sharing complex data structures that are easily corrupted like double linked lists, and avoid using locks such as mutexs as this may cause your callback function to block and therefore drop audio. Such techniques may even cause deadlock on some platforms. +You can communicate with your callback routine through the data structure you passed in on the open call, or through global variables, or using other interprocess communication techniques, but please be aware that your callback function may be called at interrupt time when your foreground process is least expecting it. So avoid sharing complex data structures that are easily corrupted like double linked lists, and avoid using locks such as mutexes as this may cause your callback function to block and therefore drop audio. Such techniques may even cause deadlock on some platforms. PortAudio will continue to call your callback and process audio until you stop the stream. This can be done in one of several ways, but, before we do so, we'll want to see that some of our audio gets processed by sleeping for a few seconds. This is easy to do with Pa_Sleep(), which is used by many of the examples in the patests/ directory for exactly this purpose. Note that, for a variety of reasons, you can not rely on this function for accurate scheduling, so your stream may not run for exactly the same amount of time as you expect, but it's good enough for our example. diff --git a/3rdparty/portaudio/doc/src/tutorial/tutorial_start.dox b/3rdparty/portaudio/doc/src/tutorial/tutorial_start.dox index d6b5e69fce3..aa4a1b9fd8f 100644 --- a/3rdparty/portaudio/doc/src/tutorial/tutorial_start.dox +++ b/3rdparty/portaudio/doc/src/tutorial/tutorial_start.dox @@ -13,14 +13,16 @@ Once you've downloaded PortAudio you'll need to compile it, which of course, dep - Windows - \ref compile_windows + - \ref compile_windows_mingw-w64 - \ref compile_windows_mingw - \ref compile_windows_asio_msvc - - \ref compile_cmake - Mac OS X - \ref compile_mac_coreaudio - POSIX - \ref compile_linux +You can also use CMake to generate project files for PortAudio on Windows, OS X or Linux or include PortAudio easily in your own CMake project. See \ref compile_cmake. + Many platforms with GCC/make can use the simple ./configure && make combination and simply use the resulting libraries in their code. @section tut_start3 Programming with PortAudio @@ -36,7 +38,9 @@ Below are the steps to writing a PortAudio application using the callback techni In addition to this "Callback" architecture, V19 also supports a "Blocking I/O" model which uses read and write calls which may be more familiar to non-audio programmers. Note that at this time, not all APIs support this functionality. -In this tutorial, we'll show how to use the callback architecture to play a sawtooth wave. Much of the tutorial is taken from the file paex_saw.c, which is part of the PortAudio distribution. When you're done with this tutorial, you'll be armed with the basic knowledge you need to write an audio program. If you need more sample code, look in the "examples" and "test" directory of the PortAudio distribution. Another great source of info is the portaudio.h Doxygen page, which documents the entire V19 API. Also see the page for tips on programming PortAudio on the PortAudio wiki. +In this tutorial, we'll show how to use the callback architecture to play a sawtooth wave. Much of the tutorial is taken from the file paex_saw.c, which is part of the PortAudio distribution. When you're done with this tutorial, you'll be armed with the basic knowledge you need to write an audio program. If you need more sample code, look in the "examples" and "test" directory of the PortAudio distribution. Another great source of info is the portaudio.h Doxygen page, which documents the entire V19 API. +Also see the page for tips on programming PortAudio +on the PortAudio wiki. @section tut_start4 Programming Tutorial Contents @@ -55,4 +59,4 @@ Once you have a basic understanding of how to use PortAudio, you might be intere Next: \ref writing_a_callback -*/ \ No newline at end of file +*/ diff --git a/3rdparty/portaudio/doc/src/tutorial/writing_a_callback.dox b/3rdparty/portaudio/doc/src/tutorial/writing_a_callback.dox index 7c2f8d3ea15..f7d71b198b3 100644 --- a/3rdparty/portaudio/doc/src/tutorial/writing_a_callback.dox +++ b/3rdparty/portaudio/doc/src/tutorial/writing_a_callback.dox @@ -10,7 +10,7 @@ The next task is to write your own "callback" function. The "callback" is a func Before we begin, it's important to realize that the callback is a delicate place. This is because some systems perform the callback in a special thread, or interrupt handler, and it is rarely treated the same as the rest of your code. For most modern systems, you won't be able to cause crashes by making disallowed calls in the callback, but if you want your code to produce glitch-free audio, you will have to make sure you avoid function calls that may take an unbounded amount of time to execute. Exactly what these are depend on your platform but almost certainly include the following: memory allocation/deallocation, I/O (including file I/O as well as console I/O, such as printf()), context switching (such as exec() or -yield()), mutex operations, or anything else that might rely on the OS. If you think short critical sections are safe please go read about priority inversion. Windows amd Mac OS schedulers have no real-time safe priority inversion prevention. Other platforms require special mutex flags. In addition, it is not safe to call any PortAudio API functions in the callback except as explicitly permitted in the documentation. +yield()), mutex operations, or anything else that might rely on the OS. If you think short critical sections are safe please go read about priority inversion. Windows and Mac OS schedulers have no real-time safe priority inversion prevention. Other platforms require special mutex flags. In addition, it is not safe to call any PortAudio API functions in the callback except as explicitly permitted in the documentation. Your callback function must return an int and accept the exact parameters specified in this typedef: diff --git a/3rdparty/portaudio/examples/CMakeLists.txt b/3rdparty/portaudio/examples/CMakeLists.txt index f96b6ec2daf..eca4beb33ae 100644 --- a/3rdparty/portaudio/examples/CMakeLists.txt +++ b/3rdparty/portaudio/examples/CMakeLists.txt @@ -1,41 +1,46 @@ # Example projects -MACRO(ADD_EXAMPLE appl_name) - ADD_EXECUTABLE(${appl_name} "${appl_name}.c") - TARGET_LINK_LIBRARIES(${appl_name} portaudio_static) - SET_TARGET_PROPERTIES(${appl_name} PROPERTIES FOLDER "Examples C") - IF(WIN32) - SET_PROPERTY(TARGET ${appl_name} APPEND_STRING PROPERTY COMPILE_DEFINITIONS _CRT_SECURE_NO_WARNINGS) - ENDIF() -ENDMACRO(ADD_EXAMPLE) +macro(add_example appl_name) + add_executable(${appl_name} "${appl_name}.c") + target_link_libraries(${appl_name} PortAudio) + if(UNIX) + target_link_libraries(${appl_name} m) + endif() + set_target_properties(${appl_name} PROPERTIES FOLDER "Examples C") + if(WIN32) + set_property(TARGET ${appl_name} APPEND_STRING PROPERTY COMPILE_DEFINITIONS _CRT_SECURE_NO_WARNINGS) + endif() +endmacro() -MACRO(ADD_EXAMPLE_CPP appl_name) - ADD_EXECUTABLE(${appl_name} "${appl_name}.cpp") - TARGET_LINK_LIBRARIES(${appl_name} portaudio_static) - SET_TARGET_PROPERTIES(${appl_name} PROPERTIES FOLDER "Examples C++") - IF(WIN32) - SET_PROPERTY(TARGET ${appl_name} APPEND_STRING PROPERTY COMPILE_DEFINITIONS _CRT_SECURE_NO_WARNINGS) - ENDIF() -ENDMACRO(ADD_EXAMPLE_CPP) +macro(add_example_cpp appl_name) + add_executable(${appl_name} "${appl_name}.cpp") + target_link_libraries(${appl_name} PortAudio) + set_target_properties(${appl_name} PROPERTIES FOLDER "Examples C++") + if(WIN32) + set_property(TARGET ${appl_name} APPEND_STRING PROPERTY COMPILE_DEFINITIONS _CRT_SECURE_NO_WARNINGS) + endif() +endmacro() -ADD_EXAMPLE(pa_devs) -ADD_EXAMPLE(pa_fuzz) -IF(PA_USE_ASIO AND WIN32) - ADD_EXAMPLE(paex_mono_asio_channel_select) -ENDIF() -ADD_EXAMPLE(paex_ocean_shore) -TARGET_INCLUDE_DIRECTORIES(paex_ocean_shore PRIVATE ../src/common) -ADD_EXAMPLE(paex_pink) -ADD_EXAMPLE(paex_read_write_wire) -ADD_EXAMPLE(paex_record) -ADD_EXAMPLE(paex_record_file) -TARGET_INCLUDE_DIRECTORIES(paex_record_file PRIVATE ../src/common) -ADD_EXAMPLE(paex_saw) -ADD_EXAMPLE(paex_sine) -ADD_EXAMPLE_CPP(paex_sine_c++) -IF(PA_USE_WMME AND WIN32) - ADD_EXAMPLE(paex_wmme_ac3) - ADD_EXAMPLE(paex_wmme_surround) -ENDIF() -ADD_EXAMPLE(paex_write_sine) -ADD_EXAMPLE(paex_write_sine_nonint) +add_example(pa_devs) +add_example(pa_fuzz) +if(PA_USE_ASIO AND WIN32) + add_example(paex_mono_asio_channel_select) +endif() +if(LINK_PRIVATE_SYMBOLS) + add_example(paex_ocean_shore) +endif() +add_example(paex_pink) +add_example(paex_read_write_wire) +add_example(paex_record) +if(LINK_PRIVATE_SYMBOLS) + add_example(paex_record_file) +endif() +add_example(paex_saw) +add_example(paex_sine) +add_example_cpp(paex_sine_c++) +if(PA_USE_WMME AND WIN32) + add_example(paex_wmme_ac3) + add_example(paex_wmme_surround) +endif() +add_example(paex_write_sine) +add_example(paex_write_sine_nonint) diff --git a/3rdparty/portaudio/examples/pa_devs.c b/3rdparty/portaudio/examples/pa_devs.c index 595a05dbe7a..27acfd53b24 100644 --- a/3rdparty/portaudio/examples/pa_devs.c +++ b/3rdparty/portaudio/examples/pa_devs.c @@ -1,7 +1,7 @@ /** @file pa_devs.c - @ingroup examples_src + @ingroup examples_src @brief List available devices, including device information. - @author Phil Burk http://www.softsynth.com + @author Phil Burk http://www.softsynth.com @note Define PA_USE_ASIO=0 to compile this code on Windows without ASIO support. @@ -34,13 +34,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -106,14 +106,14 @@ int main(void) PaStreamParameters inputParameters, outputParameters; PaError err; - + err = Pa_Initialize(); if( err != paNoError ) { printf( "ERROR: Pa_Initialize returned 0x%x\n", err ); goto error; } - + printf( "PortAudio version: 0x%08X\n", Pa_GetVersion()); printf( "Version text: '%s'\n", Pa_GetVersionInfo()->versionText ); @@ -124,13 +124,13 @@ int main(void) err = numDevices; goto error; } - + printf( "Number of devices = %d\n", numDevices ); for( i=0; iname ); defaultDisplayed = 1; } - + if( i == Pa_GetDefaultOutputDevice() ) { printf( (defaultDisplayed ? "," : "[") ); @@ -154,7 +154,7 @@ int main(void) else if( i == Pa_GetHostApiInfo( deviceInfo->hostApi )->defaultOutputDevice ) { const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo( deviceInfo->hostApi ); - printf( (defaultDisplayed ? "," : "[") ); + printf( (defaultDisplayed ? "," : "[") ); printf( " Default %s Output", hostInfo->name ); defaultDisplayed = 1; } @@ -188,7 +188,7 @@ int main(void) long minLatency, maxLatency, preferredLatency, granularity; err = PaAsio_GetAvailableLatencyValues( i, - &minLatency, &maxLatency, &preferredLatency, &granularity ); + &minLatency, &maxLatency, &preferredLatency, &granularity ); printf( "ASIO minimum buffer size = %ld\n", minLatency ); printf( "ASIO maximum buffer size = %ld\n", maxLatency ); @@ -210,7 +210,7 @@ int main(void) inputParameters.sampleFormat = paInt16; inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */ inputParameters.hostApiSpecificStreamInfo = NULL; - + outputParameters.device = i; outputParameters.channelCount = deviceInfo->maxOutputChannels; outputParameters.sampleFormat = paInt16; diff --git a/3rdparty/portaudio/examples/pa_fuzz.c b/3rdparty/portaudio/examples/pa_fuzz.c index d5f99eca269..130ea32e9fa 100644 --- a/3rdparty/portaudio/examples/pa_fuzz.c +++ b/3rdparty/portaudio/examples/pa_fuzz.c @@ -1,7 +1,7 @@ /** @file pa_fuzz.c - @ingroup examples_src + @ingroup examples_src @brief Distort input like a fuzz box. - @author Phil Burk http://www.softsynth.com + @author Phil Burk http://www.softsynth.com */ /* * $Id$ @@ -31,13 +31,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -45,9 +45,12 @@ #include #include "portaudio.h" /* -** Note that many of the older ISA sound cards on PCs do NOT support -** full duplex audio (simultaneous record and playback). -** And some only support full duplex at lower sample rates. + * Simulate a guitar distortion pedal. + * Record mono input and output clean and processed stereo output. + * + * Note that many of the older ISA sound cards on PCs do NOT support + * full duplex audio (simultaneous record and playback). + * And some only support full duplex at lower sample rates. */ #define SAMPLE_RATE (44100) #define PA_SAMPLE_TYPE paFloat32 @@ -112,11 +115,12 @@ static int fuzzCallback( const void *inputBuffer, void *outputBuffer, { for( i=0; idefaultLowInputLatency; inputParameters.hostApiSpecificStreamInfo = NULL; outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ if (outputParameters.device == paNoDevice) { - fprintf(stderr,"Error: No default output device.\n"); - goto error; + fprintf(stderr,"Error: No default output device.\n"); + goto error; } outputParameters.channelCount = 2; /* stereo output */ outputParameters.sampleFormat = PA_SAMPLE_TYPE; @@ -176,7 +180,7 @@ int main(void) error: Pa_Terminate(); - fprintf( stderr, "An error occured while using the portaudio stream\n" ); + fprintf( stderr, "An error occurred while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return -1; diff --git a/3rdparty/portaudio/examples/paex_mono_asio_channel_select.c b/3rdparty/portaudio/examples/paex_mono_asio_channel_select.c index a141ac02cf0..4b55d318578 100644 --- a/3rdparty/portaudio/examples/paex_mono_asio_channel_select.c +++ b/3rdparty/portaudio/examples/paex_mono_asio_channel_select.c @@ -1,8 +1,8 @@ /** @file paex_mono_asio_channel_select.c - @ingroup examples_src - @brief Play a monophonic sine wave on a specific ASIO channel. - @author Ross Bencina - @author Phil Burk + @ingroup examples_src + @brief Play a monophonic sine wave on a specific ASIO channel. + @author Ross Bencina + @author Phil Burk */ /* * $Id$ @@ -36,13 +36,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -114,7 +114,7 @@ int main(void) data.sine[i] = (float) (AMPLITUDE * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. )); } data.phase = 0; - + err = Pa_Initialize(); if( err != paNoError ) goto error; @@ -123,7 +123,7 @@ int main(void) outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */ outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; - /* Use an ASIO specific structure. WARNING - this is not portable. */ + /* Use an ASIO specific structure. WARNING - this is not portable. */ asioOutputInfo.size = sizeof(PaAsioStreamInfo); asioOutputInfo.hostApiType = paASIO; asioOutputInfo.version = 1; @@ -145,22 +145,22 @@ int main(void) err = Pa_StartStream( stream ); if( err != paNoError ) goto error; - + printf("Play for %d seconds.\n", NUM_SECONDS ); fflush(stdout); Pa_Sleep( NUM_SECONDS * 1000 ); err = Pa_StopStream( stream ); if( err != paNoError ) goto error; - + err = Pa_CloseStream( stream ); if( err != paNoError ) goto error; - + Pa_Terminate(); printf("Test finished.\n"); return err; error: Pa_Terminate(); - fprintf( stderr, "An error occured while using the portaudio stream\n" ); + fprintf( stderr, "An error occurred while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; diff --git a/3rdparty/portaudio/examples/paex_ocean_shore.c b/3rdparty/portaudio/examples/paex_ocean_shore.c index 7eb7f207bb6..364e7920a95 100644 --- a/3rdparty/portaudio/examples/paex_ocean_shore.c +++ b/3rdparty/portaudio/examples/paex_ocean_shore.c @@ -1,21 +1,21 @@ -/** @file paex_ocean_shore.c - @ingroup examples_src - @brief Generate Pink Noise using Gardner method, and make "waves". Provides an example of how to +/** @file paex_ocean_shore.c + @ingroup examples_src + @brief Generate Pink Noise using Gardner method, and make "waves". Provides an example of how to post stuff to/from the audio callback using lock-free FIFOs implemented by the PA ringbuffer. - Optimization suggested by James McCartney uses a tree - to select which random value to replace. + Optimization suggested by James McCartney uses a tree + to select which random value to replace.
-	x x x x x x x x x x x x x x x x 
-	x   x   x   x   x   x   x   x   
-	x       x       x       x       
-	 x               x               
-	   x   
-
- Tree is generated by counting trailing zeros in an increasing index. - When the index is zero, no random number is selected. - - @author Phil Burk http://www.softsynth.com + x x x x x x x x x x x x x x x x + x x x x x x x x + x x x x + x x + x + + Tree is generated by counting trailing zeros in an increasing index. + When the index is zero, no random number is selected. + + @author Phil Burk http://www.softsynth.com Robert Bielik */ /* @@ -46,13 +46,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -80,7 +80,7 @@ typedef struct } PinkNoise; -typedef struct +typedef struct { float bq_b0; float bq_b1; @@ -213,7 +213,7 @@ unsigned GenerateWave( OceanWave* wave, float* output, unsigned noOfFrames ) targetLevel = wave->wave_envelope_max_level; } /* Calculate lowpass biquad coeffs - + alpha = sin(w0)/(2*Q) b0 = (1 - cos(w0))/2 @@ -324,8 +324,8 @@ paTestData; static int patestCallback(const void* inputBuffer, void* outputBuffer, unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, + const PaStreamCallbackTimeInfo* timeInfo, + PaStreamCallbackFlags statusFlags, void* userData) { int i; @@ -367,7 +367,7 @@ OceanWave* InitializeWave(double SR, float attackInSeconds, float maxLevel, floa static unsigned lastNoOfRows = 12; unsigned newNoOfRows; - wave = (OceanWave*)PaUtil_AllocateMemory(sizeof(OceanWave)); + wave = (OceanWave*)PaUtil_AllocateZeroInitializedMemory(sizeof(OceanWave)); if (wave != NULL) { InitializePinkNoise(&wave->wave_left, lastNoOfRows); @@ -407,14 +407,14 @@ int main(void) static const int FPB = 128; /* Frames per buffer: 2.9 ms buffers. */ /* Initialize communication buffers (queues) */ - data.rBufToRTData = PaUtil_AllocateMemory(sizeof(OceanWave*) * 256); + data.rBufToRTData = PaUtil_AllocateZeroInitializedMemory(sizeof(OceanWave*) * 256); if (data.rBufToRTData == NULL) { return 1; } PaUtil_InitializeRingBuffer(&data.rBufToRT, sizeof(OceanWave*), 256, data.rBufToRTData); - data.rBufFromRTData = PaUtil_AllocateMemory(sizeof(OceanWave*) * 256); + data.rBufFromRTData = PaUtil_AllocateZeroInitializedMemory(sizeof(OceanWave*) * 256); if (data.rBufFromRTData == NULL) { return 1; @@ -427,8 +427,8 @@ int main(void) /* Open a stereo PortAudio stream so we can hear the result. */ outputParameters.device = Pa_GetDefaultOutputDevice(); /* Take the default output device. */ if (outputParameters.device == paNoDevice) { - fprintf(stderr,"Error: No default output device.\n"); - goto error; + fprintf(stderr,"Error: No default output device.\n"); + goto error; } outputParameters.channelCount = 2; /* Stereo output, most likely supported. */ outputParameters.hostApiSpecificStreamInfo = NULL; @@ -518,7 +518,7 @@ int main(void) { PaUtil_FreeMemory(data.rBufFromRTData); } - + Pa_Sleep(1000); Pa_Terminate(); @@ -526,7 +526,7 @@ int main(void) error: Pa_Terminate(); - fprintf( stderr, "An error occured while using the portaudio stream\n" ); + fprintf( stderr, "An error occurred while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return 0; diff --git a/3rdparty/portaudio/examples/paex_pink.c b/3rdparty/portaudio/examples/paex_pink.c index 3714ba7603a..519f9797bf5 100644 --- a/3rdparty/portaudio/examples/paex_pink.c +++ b/3rdparty/portaudio/examples/paex_pink.c @@ -1,20 +1,20 @@ /** @file paex_pink.c - @ingroup examples_src - @brief Generate Pink Noise using Gardner method. + @ingroup examples_src + @brief Generate Pink Noise using Gardner method. - Optimization suggested by James McCartney uses a tree - to select which random value to replace. + Optimization suggested by James McCartney uses a tree + to select which random value to replace.
-	x x x x x x x x x x x x x x x x 
-	x   x   x   x   x   x   x   x   
-	x       x       x       x       
-	 x               x               
-	   x   
-
- Tree is generated by counting trailing zeros in an increasing index. - When the index is zero, no random number is selected. + x x x x x x x x x x x x x x x x + x x x x x x x x + x x x x + x x + x + + Tree is generated by counting trailing zeros in an increasing index. + When the index is zero, no random number is selected. - @author Phil Burk http://www.softsynth.com + @author Phil Burk http://www.softsynth.com */ /* * $Id$ @@ -44,13 +44,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -172,8 +172,8 @@ paTestData; static int patestCallback(const void* inputBuffer, void* outputBuffer, unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, + const PaStreamCallbackTimeInfo* timeInfo, + PaStreamCallbackFlags statusFlags, void* userData) { int finished; @@ -214,7 +214,7 @@ int main(void) int totalSamps; static const double SR = 44100.0; static const int FPB = 2048; /* Frames per buffer: 46 ms buffers. */ - + /* Initialize two pink noise signals with different numbers of rows. */ InitializePinkNoise( &data.leftPink, 12 ); InitializePinkNoise( &data.rightPink, 16 ); @@ -237,8 +237,8 @@ int main(void) /* Open a stereo PortAudio stream so we can hear the result. */ outputParameters.device = Pa_GetDefaultOutputDevice(); /* Take the default output device. */ if (outputParameters.device == paNoDevice) { - fprintf(stderr,"Error: No default output device.\n"); - goto error; + fprintf(stderr,"Error: No default output device.\n"); + goto error; } outputParameters.channelCount = 2; /* Stereo output, most likely supported. */ outputParameters.hostApiSpecificStreamInfo = NULL; @@ -272,7 +272,7 @@ int main(void) return 0; error: Pa_Terminate(); - fprintf( stderr, "An error occured while using the portaudio stream\n" ); + fprintf( stderr, "An error occurred while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return 0; diff --git a/3rdparty/portaudio/examples/paex_read_write_wire.c b/3rdparty/portaudio/examples/paex_read_write_wire.c index 4208a019efb..46fc8bc40bc 100644 --- a/3rdparty/portaudio/examples/paex_read_write_wire.c +++ b/3rdparty/portaudio/examples/paex_read_write_wire.c @@ -1,7 +1,7 @@ /** @file paex_read_write_wire.c - @ingroup examples_src - @brief Tests full duplex blocking I/O by passing input straight to output. - @author Bjorn Roche. XO Audio LLC for Z-Systems Engineering. + @ingroup examples_src + @brief Tests full duplex blocking I/O by passing input straight to output. + @author Bjorn Roche. XO Audio LLC for Z-Systems Engineering. @author based on code by: Phil Burk http://www.softsynth.com @author based on code by: Ross Bencina rossb@audiomulch.com */ @@ -98,8 +98,8 @@ int main(void) int numChannels; printf("patest_read_write_wire.c\n"); fflush(stdout); - printf("sizeof(int) = %lu\n", sizeof(int)); fflush(stdout); - printf("sizeof(long) = %lu\n", sizeof(long)); fflush(stdout); + printf("sizeof(int) = %lu\n", (unsigned long) sizeof(int)); fflush(stdout); + printf("sizeof(long) = %lu\n", (unsigned long) sizeof(long)); fflush(stdout); err = Pa_Initialize(); if( err != paNoError ) goto error2; @@ -179,27 +179,26 @@ int main(void) xrun: printf("err = %d\n", err); fflush(stdout); if( stream ) { - Pa_AbortStream( stream ); - Pa_CloseStream( stream ); + Pa_AbortStream( stream ); + Pa_CloseStream( stream ); } free( sampleBlock ); Pa_Terminate(); if( err & paInputOverflow ) - fprintf( stderr, "Input Overflow.\n" ); + fprintf( stderr, "Input Overflow.\n" ); if( err & paOutputUnderflow ) - fprintf( stderr, "Output Underflow.\n" ); + fprintf( stderr, "Output Underflow.\n" ); return -2; error1: free( sampleBlock ); error2: if( stream ) { - Pa_AbortStream( stream ); - Pa_CloseStream( stream ); + Pa_AbortStream( stream ); + Pa_CloseStream( stream ); } Pa_Terminate(); - fprintf( stderr, "An error occured while using the portaudio stream\n" ); + fprintf( stderr, "An error occurred while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return -1; } - diff --git a/3rdparty/portaudio/examples/paex_record.c b/3rdparty/portaudio/examples/paex_record.c index 99226fca84e..02724d89fd1 100644 --- a/3rdparty/portaudio/examples/paex_record.c +++ b/3rdparty/portaudio/examples/paex_record.c @@ -1,7 +1,7 @@ /** @file paex_record.c - @ingroup examples_src - @brief Record input into an array; Save array to a file; Playback recorded data. - @author Phil Burk http://www.softsynth.com + @ingroup examples_src + @brief Record input into an array; Save array to a file; Playback recorded data. + @author Phil Burk http://www.softsynth.com */ /* * $Id$ @@ -31,13 +31,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -49,7 +49,7 @@ #define SAMPLE_RATE (44100) #define FRAMES_PER_BUFFER (512) #define NUM_SECONDS (5) -#define NUM_CHANNELS (2) +#define NUM_CHANNELS (1) /* #define DITHER_FLAG (paDitherOff) */ #define DITHER_FLAG (0) /**/ /** Set to 1 if you want to capture the recording to a file. */ @@ -229,7 +229,7 @@ int main(void) fprintf(stderr,"Error: No default input device.\n"); goto done; } - inputParameters.channelCount = 2; /* stereo input */ + inputParameters.channelCount = NUM_CHANNELS; inputParameters.sampleFormat = PA_SAMPLE_TYPE; inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency; inputParameters.hostApiSpecificStreamInfo = NULL; @@ -305,7 +305,7 @@ int main(void) fprintf(stderr,"Error: No default output device.\n"); goto done; } - outputParameters.channelCount = 2; /* stereo output */ + outputParameters.channelCount = NUM_CHANNELS; outputParameters.sampleFormat = PA_SAMPLE_TYPE; outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; @@ -326,15 +326,15 @@ int main(void) { err = Pa_StartStream( stream ); if( err != paNoError ) goto done; - + printf("Waiting for playback to finish.\n"); fflush(stdout); while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(100); if( err < 0 ) goto done; - + err = Pa_CloseStream( stream ); if( err != paNoError ) goto done; - + printf("Done.\n"); fflush(stdout); } @@ -344,11 +344,10 @@ done: free( data.recordedSamples ); if( err != paNoError ) { - fprintf( stderr, "An error occured while using the portaudio stream\n" ); + fprintf( stderr, "An error occurred while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); err = 1; /* Always return 0 or 1, but no other return codes. */ } return err; } - diff --git a/3rdparty/portaudio/examples/paex_record_file.c b/3rdparty/portaudio/examples/paex_record_file.c index 1f1211fce98..f1276ecbed4 100644 --- a/3rdparty/portaudio/examples/paex_record_file.c +++ b/3rdparty/portaudio/examples/paex_record_file.c @@ -1,7 +1,7 @@ /** @file paex_record_file.c - @ingroup examples_src - @brief Record input into a file, then playback recorded data from file (Windows only at the moment) - @author Robert Bielik + @ingroup examples_src + @brief Record input into a file, then playback recorded data from file (Windows only at the moment) + @author Robert Bielik */ /* * $Id: paex_record_file.c 1752 2011-09-08 03:21:55Z philburk $ @@ -31,13 +31,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -315,7 +315,7 @@ int main(void) /* We set the ring buffer size to about 500 ms */ numSamples = NextPowerOf2((unsigned)(SAMPLE_RATE * 0.5 * NUM_CHANNELS)); numBytes = numSamples * sizeof(SAMPLE); - data.ringBufferData = (SAMPLE *) PaUtil_AllocateMemory( numBytes ); + data.ringBufferData = (SAMPLE *) PaUtil_AllocateZeroInitializedMemory( numBytes ); if( data.ringBufferData == NULL ) { printf("Could not allocate ring buffer data.\n"); @@ -433,12 +433,12 @@ int main(void) } if( err < 0 ) goto done; } - + err = Pa_CloseStream( stream ); if( err != paNoError ) goto done; fclose(data.file); - + printf("Done.\n"); fflush(stdout); } @@ -448,11 +448,10 @@ done: PaUtil_FreeMemory( data.ringBufferData ); if( err != paNoError ) { - fprintf( stderr, "An error occured while using the portaudio stream\n" ); + fprintf( stderr, "An error occurred while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); err = 1; /* Always return 0 or 1, but no other return codes. */ } return err; } - diff --git a/3rdparty/portaudio/examples/paex_saw.c b/3rdparty/portaudio/examples/paex_saw.c index 235f247e92b..caec0b02d7e 100644 --- a/3rdparty/portaudio/examples/paex_saw.c +++ b/3rdparty/portaudio/examples/paex_saw.c @@ -1,7 +1,7 @@ /** @file paex_saw.c - @ingroup examples_src - @brief Play a simple (aliasing) sawtooth wave. - @author Phil Burk http://www.softsynth.com + @ingroup examples_src + @brief Play a simple (aliasing) sawtooth wave. + @author Phil Burk http://www.softsynth.com */ /* * $Id$ @@ -31,13 +31,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -92,14 +92,14 @@ int main(void) { PaStream *stream; PaError err; - + printf("PortAudio Test: output sawtooth wave.\n"); /* Initialize our data for use by callback. */ data.left_phase = data.right_phase = 0.0; /* Initialize library before making any other calls. */ err = Pa_Initialize(); if( err != paNoError ) goto error; - + /* Open an audio I/O stream. */ err = Pa_OpenDefaultStream( &stream, 0, /* no input channels */ @@ -126,7 +126,7 @@ int main(void) return err; error: Pa_Terminate(); - fprintf( stderr, "An error occured while using the portaudio stream\n" ); + fprintf( stderr, "An error occurred while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; diff --git a/3rdparty/portaudio/examples/paex_sine.c b/3rdparty/portaudio/examples/paex_sine.c index bda290b8ead..50ef205c9b1 100644 --- a/3rdparty/portaudio/examples/paex_sine.c +++ b/3rdparty/portaudio/examples/paex_sine.c @@ -1,7 +1,7 @@ /** @file paex_sine.c - @ingroup examples_src - @brief Play a sine wave for several seconds. - @author Ross Bencina + @ingroup examples_src + @brief Play a sine wave for several seconds. + @author Ross Bencina @author Phil Burk */ /* @@ -32,13 +32,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ #include @@ -80,7 +80,7 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer, (void) timeInfo; /* Prevent unused variable warnings. */ (void) statusFlags; (void) inputBuffer; - + for( i=0; isine[data->left_phase]; /* left */ @@ -90,7 +90,7 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer, data->right_phase += 3; /* higher pitch so we can distinguish left and right. */ if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE; } - + return paContinue; } @@ -99,8 +99,8 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer, */ static void StreamFinished( void* userData ) { - paTestData *data = (paTestData *) userData; - printf( "Stream Completed: %s\n", data->message ); + paTestData *data = (paTestData *) userData; + printf( "Stream Completed: %s\n", data->message ); } /*******************************************************************/ @@ -121,14 +121,14 @@ int main(void) data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ); } data.left_phase = data.right_phase = 0; - + err = Pa_Initialize(); if( err != paNoError ) goto error; outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ if (outputParameters.device == paNoDevice) { - fprintf(stderr,"Error: No default output device.\n"); - goto error; + fprintf(stderr,"Error: No default output device.\n"); + goto error; } outputParameters.channelCount = 2; /* stereo output */ outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */ @@ -164,11 +164,11 @@ int main(void) Pa_Terminate(); printf("Test finished.\n"); - + return err; error: Pa_Terminate(); - fprintf( stderr, "An error occured while using the portaudio stream\n" ); + fprintf( stderr, "An error occurred while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; diff --git a/3rdparty/portaudio/examples/paex_sine_c++.cpp b/3rdparty/portaudio/examples/paex_sine_c++.cpp index 2859a57867c..5d965222b11 100644 --- a/3rdparty/portaudio/examples/paex_sine_c++.cpp +++ b/3rdparty/portaudio/examples/paex_sine_c++.cpp @@ -1,7 +1,7 @@ /** @file paex_sine.c - @ingroup examples_src - @brief Play a sine wave for several seconds. - @author Ross Bencina + @ingroup examples_src + @brief Play a sine wave for several seconds. + @author Ross Bencina @author Phil Burk */ /* @@ -32,13 +32,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ #include @@ -189,7 +189,7 @@ private: PaStreamCallbackFlags statusFlags, void *userData ) { - /* Here we cast userData to Sine* type so we can call the instance method paCallbackMethod, we can do that since + /* Here we cast userData to Sine* type so we can call the instance method paCallbackMethod, we can do that since we called Pa_OpenStream with 'this' for userData */ return ((Sine*)userData)->paCallbackMethod(inputBuffer, outputBuffer, framesPerBuffer, @@ -247,7 +247,7 @@ int main(void) Sine sine; printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER); - + ScopedPaHandler paInit; if( paInit.result() != paNoError ) goto error; @@ -268,7 +268,7 @@ int main(void) return paNoError; error: - fprintf( stderr, "An error occured while using the portaudio stream\n" ); + fprintf( stderr, "An error occurred while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", paInit.result() ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( paInit.result() ) ); return 1; diff --git a/3rdparty/portaudio/examples/paex_wmme_ac3.c b/3rdparty/portaudio/examples/paex_wmme_ac3.c index e59c571f420..74daa96fd84 100644 --- a/3rdparty/portaudio/examples/paex_wmme_ac3.c +++ b/3rdparty/portaudio/examples/paex_wmme_ac3.c @@ -1,7 +1,7 @@ /** @file paex_wmme_ac3.c - @ingroup examples_src - @brief Use WMME-specific interface to send raw AC3 data to a S/PDIF output. - @author Ross Bencina + @ingroup examples_src + @brief Use WMME-specific interface to send raw AC3 data to a S/PDIF output. + @author Ross Bencina */ /* * $Id: $ @@ -31,13 +31,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -91,17 +91,17 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer, (void) inputBuffer; /* stream out contents of data->buffer looping at end */ - + for( i=0; ibuffer[ data->playbackIndex++ ]; if( data->playbackIndex >= data->bufferSampleCount ) data->playbackIndex = 0; /* loop at end of buffer */ - } - } - + } + } + return paContinue; } @@ -120,10 +120,10 @@ int main(int argc, char* argv[]) printf("usage: patest_wmme_ac3 fileName [paDeviceIndex]\n"); printf("**IMPORTANT*** The provided file must include the spdif preamble at the start of every AC-3 frame. Using a normal ac3 file won't work.\n"); - printf("PortAudio Test: output a raw spdif ac3 stream. SR = %d, BufSize = %d, Chans = %d\n", + printf("PortAudio Test: output a raw spdif ac3 stream. SR = %d, BufSize = %d, Chans = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER, CHANNEL_COUNT); - + if( argc >= 2 ) fileName = argv[1]; @@ -154,14 +154,14 @@ int main(int argc, char* argv[]) err = Pa_Initialize(); if( err != paNoError ) goto error; - deviceIndex = Pa_GetHostApiInfo( Pa_HostApiTypeIdToHostApiIndex( paMME ) )->defaultOutputDevice; - if( argc >= 3 ){ - sscanf( argv[1], "%d", &deviceIndex ); - } + deviceIndex = Pa_GetHostApiInfo( Pa_HostApiTypeIdToHostApiIndex( paMME ) )->defaultOutputDevice; + if( argc >= 3 ){ + sscanf( argv[1], "%d", &deviceIndex ); + } + + printf( "using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name ); - printf( "using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name ); - outputParameters.device = deviceIndex; outputParameters.channelCount = CHANNEL_COUNT; outputParameters.sampleFormat = paInt16; /* IMPORTANT must use paInt16 for WMME AC3 */ @@ -169,17 +169,17 @@ int main(int argc, char* argv[]) outputParameters.hostApiSpecificStreamInfo = NULL; wmmeStreamInfo.size = sizeof(PaWinMmeStreamInfo); - wmmeStreamInfo.hostApiType = paMME; + wmmeStreamInfo.hostApiType = paMME; wmmeStreamInfo.version = 1; wmmeStreamInfo.flags = paWinMmeWaveFormatDolbyAc3Spdif; outputParameters.hostApiSpecificStreamInfo = &wmmeStreamInfo; - if( Pa_IsFormatSupported( 0, &outputParameters, SAMPLE_RATE ) == paFormatIsSupported ){ - printf( "Pa_IsFormatSupported reports device will support %d channels.\n", CHANNEL_COUNT ); - }else{ - printf( "Pa_IsFormatSupported reports device will not support %d channels.\n", CHANNEL_COUNT ); - } + if( Pa_IsFormatSupported( 0, &outputParameters, SAMPLE_RATE ) == paFormatIsSupported ){ + printf( "Pa_IsFormatSupported reports device will support %d channels.\n", CHANNEL_COUNT ); + }else{ + printf( "Pa_IsFormatSupported reports device will not support %d channels.\n", CHANNEL_COUNT ); + } err = Pa_OpenStream( &stream, @@ -207,15 +207,14 @@ int main(int argc, char* argv[]) Pa_Terminate(); free( data.buffer ); printf("Test finished.\n"); - + return err; error: Pa_Terminate(); free( data.buffer ); - fprintf( stderr, "An error occured while using the portaudio stream\n" ); + fprintf( stderr, "An error occurred while using the portaudio stream\n" ); fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); return err; } - diff --git a/3rdparty/portaudio/examples/paex_wmme_surround.c b/3rdparty/portaudio/examples/paex_wmme_surround.c index ddab73da0d1..55fc2551316 100644 --- a/3rdparty/portaudio/examples/paex_wmme_surround.c +++ b/3rdparty/portaudio/examples/paex_wmme_surround.c @@ -1,7 +1,7 @@ /** @file paex_wmme_surround.c - @ingroup examples_src - @brief Use WMME-specific channelMask to request 5.1 surround sound output. - @author Ross Bencina + @ingroup examples_src + @brief Use WMME-specific channelMask to request 5.1 surround sound output. + @author Ross Bencina */ /* * $Id: $ @@ -31,13 +31,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -67,9 +67,9 @@ typedef struct { float sine[TABLE_SIZE]; - int phase; - int currentChannel; - int cycleCount; + int phase; + int currentChannel; + int cycleCount; } paTestData; @@ -90,31 +90,31 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer, (void) timeInfo; /* Prevent unused variable warnings. */ (void) statusFlags; (void) inputBuffer; - + for( i=0; icurrentChannel && data->cycleCount < 4410 ){ - *out++ = data->sine[data->phase]; - data->phase += 1 + j; // play each channel at a different pitch so they can be distinguished - if( data->phase >= TABLE_SIZE ){ - data->phase -= TABLE_SIZE; - } - }else{ - *out++ = 0; - } - } - - data->cycleCount++; - if( data->cycleCount > 44100 ){ - data->cycleCount = 0; - - ++data->currentChannel; - if( data->currentChannel >= CHANNEL_COUNT ) - data->currentChannel -= CHANNEL_COUNT; - } - } - + for( j = 0; j < CHANNEL_COUNT; ++j ){ + if( j == data->currentChannel && data->cycleCount < 4410 ){ + *out++ = data->sine[data->phase]; + data->phase += 1 + j; // play each channel at a different pitch so they can be distinguished + if( data->phase >= TABLE_SIZE ){ + data->phase -= TABLE_SIZE; + } + }else{ + *out++ = 0; + } + } + + data->cycleCount++; + if( data->cycleCount > 44100 ){ + data->cycleCount = 0; + + ++data->currentChannel; + if( data->currentChannel >= CHANNEL_COUNT ) + data->currentChannel -= CHANNEL_COUNT; + } + } + return paContinue; } @@ -134,12 +134,12 @@ int main(int argc, char* argv[]) err = Pa_Initialize(); if( err != paNoError ) goto error; - deviceIndex = Pa_GetHostApiInfo( Pa_HostApiTypeIdToHostApiIndex( paMME ) )->defaultOutputDevice; - if( argc == 2 ){ - sscanf( argv[1], "%d", &deviceIndex ); - } + deviceIndex = Pa_GetHostApiInfo( Pa_HostApiTypeIdToHostApiIndex( paMME ) )->defaultOutputDevice; + if( argc == 2 ){ + sscanf( argv[1], "%d", &deviceIndex ); + } - printf( "using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name ); + printf( "using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name ); /* initialise sinusoidal wavetable */ for( i=0; i + @ingroup examples_src + @brief Play a sine wave for several seconds using the blocking API (Pa_WriteStream()) + @author Ross Bencina @author Phil Burk */ /* @@ -32,13 +32,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -71,23 +71,23 @@ int main(void) int right_inc = 3; /* higher pitch so we can distinguish left and right. */ int i, j, k; int bufferCount; - + printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER); - + /* initialise sinusoidal wavetable */ for( i=0; ierrorCode, hostErrorInfo->hostApiType ); - fprintf( stderr, "Host API error = %s\n", hostErrorInfo->errorText ); - } + // Print more information about the error. + if( err == paUnanticipatedHostError ) + { + const PaHostErrorInfo *hostErrorInfo = Pa_GetLastHostErrorInfo(); + fprintf( stderr, "Host API error = #%ld, hostApiType = %d\n", hostErrorInfo->errorCode, hostErrorInfo->hostApiType ); + fprintf( stderr, "Host API error = %s\n", hostErrorInfo->errorText ); + } Pa_Terminate(); return err; } diff --git a/3rdparty/portaudio/examples/paex_write_sine_nonint.c b/3rdparty/portaudio/examples/paex_write_sine_nonint.c index 3a038e18588..db78ed74d35 100644 --- a/3rdparty/portaudio/examples/paex_write_sine_nonint.c +++ b/3rdparty/portaudio/examples/paex_write_sine_nonint.c @@ -1,7 +1,7 @@ /** @file paex_write_sine_nonint.c - @ingroup examples_src - @brief Play a non-interleaved sine wave using the blocking API (Pa_WriteStream()) - @author Ross Bencina + @ingroup examples_src + @brief Play a non-interleaved sine wave using the blocking API (Pa_WriteStream()) + @author Ross Bencina @author Phil Burk */ /* @@ -32,13 +32,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -63,11 +63,11 @@ int main(void) PaStreamParameters outputParameters; PaStream *stream; PaError err; - - float leftBuffer[FRAMES_PER_BUFFER]; + + float leftBuffer[FRAMES_PER_BUFFER]; float rightBuffer[FRAMES_PER_BUFFER]; void *buffers[2]; /* points to both non-interleaved buffers. */ - + float sine[TABLE_SIZE]; /* sine wavetable */ int left_phase = 0; int right_phase = 0; @@ -76,23 +76,23 @@ int main(void) int i, j, k; int bufferCount; - + printf("PortAudio Test: output sine wave NON-INTERLEAVED. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER); - + /* initialise sinusoidal wavetable */ for( i=0; i ids, names; + std::vector role; + + ids.resize(count); + names.resize(count); + role.resize(count); + + for (UINT32 i = 0; i < count; ++i) + { + ids[i] = (const UINT16 *)device_ids[i].c_str(); + names[i] = (const UINT16 *)device_names[i].c_str(); + role[i] = eRoleUnknownFormFactor; + } + + PaWasapiWinrt_SetDefaultDeviceId((const UINT16 *)default_device_id.c_str(), !capture); + PaWasapiWinrt_PopulateDeviceList(ids.data(), names.data(), role.data(), count, !capture); + PaWasapi_UpdateDeviceList(); + + ---------------- */ #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* PA_WIN_WASAPI_H */ +#endif /* PA_WIN_WASAPI_H */ diff --git a/3rdparty/portaudio/include/pa_win_waveformat.h b/3rdparty/portaudio/include/pa_win_waveformat.h index 2c00267117d..251562d0fb6 100644 --- a/3rdparty/portaudio/include/pa_win_waveformat.h +++ b/3rdparty/portaudio/include/pa_win_waveformat.h @@ -29,13 +29,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -49,87 +49,87 @@ 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. + 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) +#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) +#define PAWIN_SPEAKER_RESERVED ((PaWinWaveFormatChannelMask)0x7FFC0000) /* Used to specify that any possible permutation of speaker configurations */ -#define PAWIN_SPEAKER_ALL ((PaWinWaveFormatChannelMask)0x80000000) +#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) +#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 +#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 +#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. + 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 + 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. */ @@ -138,24 +138,24 @@ typedef unsigned long PaWinWaveFormatChannelMask; typedef struct{ unsigned char fields[ PAWIN_SIZEOF_WAVEFORMATEXTENSIBLE ]; - unsigned long extraLongForAlignment; /* ensure that compiler aligns struct to DWORD */ + unsigned long extraLongForAlignment; /* ensure that compiler aligns struct to DWORD */ } PaWinWaveFormat; /* WAVEFORMATEXTENSIBLE fields: - + union { - WORD wValidBitsPerSample; - WORD wSamplesPerBlock; - WORD wReserved; + WORD wValidBitsPerSample; + WORD wSamplesPerBlock; + WORD wReserved; } Samples; - DWORD dwChannelMask; + 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) +#define PAWIN_INDEXOF_WVALIDBITSPERSAMPLE (PAWIN_SIZEOF_WAVEFORMATEX+0) +#define PAWIN_INDEXOF_DWCHANNELMASK (PAWIN_SIZEOF_WAVEFORMATEX+2) +#define PAWIN_INDEXOF_SUBFORMAT (PAWIN_SIZEOF_WAVEFORMATEX+6) /* @@ -163,10 +163,10 @@ typedef struct{ 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) +#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) /* @@ -176,16 +176,16 @@ typedef struct{ int PaWin_SampleFormatToLinearWaveFormatTag( PaSampleFormat sampleFormat ); /* - Use the following two functions to initialize the waveformat structure. + 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_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 ); +void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat, + int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate, + PaWinWaveFormatChannelMask channelMask ); /* Map a channel count to a speaker channel mask */ @@ -196,4 +196,4 @@ PaWinWaveFormatChannelMask PaWin_DefaultChannelMask( int numChannels ); } #endif /* __cplusplus */ -#endif /* PA_WIN_WAVEFORMAT_H */ \ No newline at end of file +#endif /* PA_WIN_WAVEFORMAT_H */ diff --git a/3rdparty/portaudio/include/pa_win_wdmks.h b/3rdparty/portaudio/include/pa_win_wdmks.h index 35929625e2c..bc2f6897c57 100644 --- a/3rdparty/portaudio/include/pa_win_wdmks.h +++ b/3rdparty/portaudio/include/pa_win_wdmks.h @@ -28,13 +28,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -134,4 +134,4 @@ extern "C" } #endif /* __cplusplus */ -#endif /* PA_WIN_DS_H */ +#endif /* PA_WIN_DS_H */ diff --git a/3rdparty/portaudio/include/pa_win_wmme.h b/3rdparty/portaudio/include/pa_win_wmme.h index f84b68b892d..814022b1eac 100644 --- a/3rdparty/portaudio/include/pa_win_wmme.h +++ b/3rdparty/portaudio/include/pa_win_wmme.h @@ -28,13 +28,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -52,7 +52,7 @@ extern "C" #endif /* __cplusplus */ -/* The following are flags which can be set in +/* The following are flags which can be set in PaWinMmeStreamInfo's flags field. */ @@ -100,7 +100,7 @@ typedef struct PaWinMmeStreamInfo{ Pa_OpenStream(). */ unsigned long framesPerBuffer; - unsigned long bufferCount; /* formerly numBuffers */ + unsigned long bufferCount; /* formerly numBuffers */ /* multiple devices per direction support If flags contains the PaWinMmeUseMultipleDevices flag, @@ -109,7 +109,7 @@ typedef struct PaWinMmeStreamInfo{ 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 + The total number of channels across all specified devices must agree with the corresponding channelCount parameter to Pa_OpenStream() otherwise a paInvalidChannelCount error will result. */ @@ -118,7 +118,7 @@ typedef struct PaWinMmeStreamInfo{ /* support for WAVEFORMATEXTENSIBLE channel masks. If flags contains - paWinMmeUseChannelMask this allows you to specify which speakers + paWinMmeUseChannelMask this allows you to specify which speakers to address in a multichannel stream. Constants for channelMask are specified in pa_win_waveformat.h @@ -155,7 +155,7 @@ 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. @@ -182,4 +182,4 @@ HWAVEOUT PaWinMME_GetStreamOutputHandle( PaStream* stream, int handleIndex ); } #endif /* __cplusplus */ -#endif /* PA_WIN_WMME_H */ +#endif /* PA_WIN_WMME_H */ diff --git a/3rdparty/portaudio/include/portaudio.h b/3rdparty/portaudio/include/portaudio.h index 8a94aafbbb8..8a8250fa258 100644 --- a/3rdparty/portaudio/include/portaudio.h +++ b/3rdparty/portaudio/include/portaudio.h @@ -29,13 +29,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -100,7 +100,7 @@ typedef struct PaVersionInfo { /** Version as a string, for example "PortAudio V19.5.0-devel, revision 1952M" */ const char *versionText; } PaVersionInfo; - + /** Retrieve version information for the currently running PortAudio build. @return A pointer to an immutable PaVersionInfo structure. @@ -111,7 +111,7 @@ typedef struct PaVersionInfo { @see PaVersionInfo, paMakeVersionNumber @version Available as of 19.5.0. */ -const PaVersionInfo* Pa_GetVersionInfo(); +const PaVersionInfo* Pa_GetVersionInfo( void ); /** Error codes returned by PortAudio functions. @@ -167,9 +167,9 @@ const char *Pa_GetErrorText( PaError errorCode ); and Pa_GetErrorText(), this function MUST be called before using any other PortAudio API functions. - If Pa_Initialize() is called multiple times, each successful - call must be matched with a corresponding call to Pa_Terminate(). - Pairs of calls to Pa_Initialize()/Pa_Terminate() may overlap, and are not + If Pa_Initialize() is called multiple times, each successful + call must be matched with a corresponding call to Pa_Terminate(). + Pairs of calls to Pa_Initialize()/Pa_Terminate() may overlap, and are not required to be fully nested. Note that if Pa_Initialize() returns an error code, Pa_Terminate() should @@ -196,7 +196,7 @@ PaError Pa_Initialize( void ); @return paNoError if successful, otherwise an error code indicating the cause of failure. - + @see Pa_Initialize */ PaError Pa_Terminate( void ); @@ -287,7 +287,8 @@ typedef enum PaHostApiTypeId paWDMKS=11, paJACK=12, paWASAPI=13, - paAudioScienceHPI=14 + paAudioScienceHPI=14, + paAudioIO=15 } PaHostApiTypeId; @@ -320,7 +321,7 @@ typedef struct PaHostApiInfo if no default output device is available. */ PaDeviceIndex defaultOutputDevice; - + } PaHostApiInfo; @@ -349,7 +350,7 @@ const PaHostApiInfo * Pa_GetHostApiInfo( PaHostApiIndex hostApi ); @return A valid PaHostApiIndex ranging from 0 to (Pa_GetHostApiCount()-1) or, a PaErrorCode (which are always negative) if PortAudio is not initialized or an error is encountered. - + The paHostApiNotFound error code indicates that the host API specified by the type parameter is not available. @@ -376,7 +377,7 @@ PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type ); A paInvalidDevice error code indicates that the hostApiDeviceIndex parameter is out of range. - + @see PaHostApiInfo */ PaDeviceIndex Pa_HostApiDeviceIndexToDeviceIndex( PaHostApiIndex hostApi, @@ -449,12 +450,12 @@ PaDeviceIndex Pa_GetDefaultInputDevice( void ); PaDeviceIndex Pa_GetDefaultOutputDevice( void ); -/** The type used to represent monotonic time in seconds. PaTime is - used for the fields of the PaStreamCallbackTimeInfo argument to the +/** The type used to represent monotonic time in seconds. PaTime is + used for the fields of the PaStreamCallbackTimeInfo argument to the PaStreamCallback and as the result of Pa_GetStreamTime(). PaTime values have unspecified origin. - + @see PaStreamCallback, PaStreamCallbackTimeInfo, Pa_GetStreamTime */ typedef double PaTime; @@ -472,7 +473,7 @@ typedef double PaTime; paUInt8 is an unsigned 8 bit format where 128 is considered "ground" - The paNonInterleaved flag indicates that audio data is passed as an array + The paNonInterleaved flag indicates that audio data is passed as an array of pointers to separate buffers, one buffer for each channel. Usually, when this flag is not used, audio data is passed as a single buffer with all channels interleaved. @@ -502,7 +503,7 @@ typedef struct PaDeviceInfo int structVersion; /* this is struct version 2 */ const char *name; PaHostApiIndex hostApi; /**< note this is a host API index, not a type id*/ - + int maxInputChannels; int maxOutputChannels; @@ -544,7 +545,7 @@ typedef struct PaStreamParameters This field must not be set to paNoDevice. */ PaDeviceIndex device; - + /** The number of channels of sound to be delivered to the stream callback or accessed by Pa_ReadStream() or Pa_WriteStream(). It can range from 1 to the value of maxInputChannels in the @@ -619,9 +620,9 @@ PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters, A single PaStream can provide multiple channels of real-time streaming audio input and output to a client application. A stream provides access to audio hardware represented by one or more - PaDevices. Depending on the underlying Host API, it may be possible - to open multiple streams using the same device, however this behavior - is implementation defined. Portable applications should assume that + PaDevices. Depending on the underlying Host API, it may be possible + to open multiple streams using the same device, however this behavior + is implementation defined. Portable applications should assume that a PaDevice may be simultaneously used by at most one PaStream. Pointers to PaStream objects are passed between PortAudio functions that @@ -679,7 +680,7 @@ typedef unsigned long PaStreamFlags; /** Call the stream callback to fill initial output buffers, rather than the default behavior of priming the buffers with zeros (silence). This flag has no effect for input-only and blocking read/write streams. - + @see PaStreamFlags */ #define paPrimeOutputBuffersUsingStreamCallback ((PaStreamFlags) 0x00000008) @@ -693,7 +694,7 @@ typedef unsigned long PaStreamFlags; Timing information for the buffers passed to the stream callback. Time values are expressed in seconds and are synchronised with the time base used by Pa_GetStreamTime() for the associated stream. - + @see PaStreamCallback, Pa_GetStreamTime */ typedef struct PaStreamCallbackTimeInfo{ @@ -764,41 +765,41 @@ typedef enum PaStreamCallbackResult active PortAudio stream. When a stream is running, PortAudio calls the stream callback periodically. - The callback function is responsible for processing buffers of audio samples + The callback function is responsible for processing buffers of audio samples passed via the input and output parameters. The PortAudio stream callback runs at very high or real-time priority. - It is required to consistently meet its time deadlines. Do not allocate - memory, access the file system, call library functions or call other functions + It is required to consistently meet its time deadlines. Do not allocate + memory, access the file system, call library functions or call other functions from the stream callback that may block or take an unpredictable amount of time to complete. In order for a stream to maintain glitch-free operation the callback must consume and return audio data faster than it is recorded and/or - played. PortAudio anticipates that each callback invocation may execute for - a duration approaching the duration of frameCount audio frames at the stream + played. PortAudio anticipates that each callback invocation may execute for + a duration approaching the duration of frameCount audio frames at the stream sample rate. It is reasonable to expect to be able to utilise 70% or more of - the available CPU time in the PortAudio callback. However, due to buffer size - adaption and other factors, not all host APIs are able to guarantee audio - stability under heavy CPU load with arbitrary fixed callback buffer sizes. - When high callback CPU utilisation is required the most robust behavior - can be achieved by using paFramesPerBufferUnspecified as the + the available CPU time in the PortAudio callback. However, due to buffer size + adaption and other factors, not all host APIs are able to guarantee audio + stability under heavy CPU load with arbitrary fixed callback buffer sizes. + When high callback CPU utilisation is required the most robust behavior + can be achieved by using paFramesPerBufferUnspecified as the Pa_OpenStream() framesPerBuffer parameter. - + @param input and @param output are either arrays of interleaved samples or; - if non-interleaved samples were requested using the paNonInterleaved sample - format flag, an array of buffer pointers, one non-interleaved buffer for + if non-interleaved samples were requested using the paNonInterleaved sample + format flag, an array of buffer pointers, one non-interleaved buffer for each channel. The format, packing and number of channels used by the buffers are determined by parameters to Pa_OpenStream(). - + @param frameCount The number of sample frames to be processed by the stream callback. @param timeInfo Timestamps indicating the ADC capture time of the first sample in the input buffer, the DAC output time of the first sample in the output buffer - and the time the callback was invoked. + and the time the callback was invoked. See PaStreamCallbackTimeInfo and Pa_GetStreamTime() @param statusFlags Flags indicating whether input and/or output buffers @@ -836,10 +837,10 @@ typedef int PaStreamCallback( /** Opens a stream for either input, output or both. - + @param stream The address of a PaStream pointer which will receive a pointer to the newly opened stream. - + @param inputParameters A structure that describes the input parameters used by the opened stream. See PaStreamParameters for a description of these parameters. inputParameters must be NULL for output-only streams. @@ -847,10 +848,13 @@ typedef int PaStreamCallback( @param outputParameters A structure that describes the output parameters used by the opened stream. See PaStreamParameters for a description of these parameters. outputParameters must be NULL for input-only streams. - + @param sampleRate The desired sampleRate. For full-duplex streams it is the - sample rate for both input and output - + sample rate for both input and output. Note that the actual sampleRate + may differ very slightly from the desired rate because of hardware limitations. + The exact rate can be queried using Pa_GetStreamInfo(). If nothing close + to the desired sampleRate is available then the open will fail and return an error. + @param framesPerBuffer The number of frames passed to the stream callback function, or the preferred block granularity for a blocking read/write stream. The special value paFramesPerBufferUnspecified (0) may be used to request that @@ -862,11 +866,11 @@ typedef int PaStreamCallback( will be kept to the theoretical minimum however, it is strongly recommended that a non-zero framesPerBuffer value only be used when your algorithm requires a fixed number of frames per stream callback. - + @param streamFlags Flags which modify the behavior of the streaming process. This parameter may contain a combination of flags ORed together. Some flags may only be relevant to certain buffer formats. - + @param streamCallback A pointer to a client supplied function that is responsible for processing and filling input and output buffers. If this parameter is NULL the stream will be opened in 'blocking read/write' mode. In blocking mode, @@ -879,7 +883,7 @@ typedef int PaStreamCallback( function. It could for example, contain a pointer to instance data necessary for processing the audio buffers. This parameter is ignored if streamCallback is NULL. - + @return Upon success Pa_OpenStream() returns paNoError and places a pointer to a valid PaStream in the stream argument. The stream is inactive (stopped). @@ -904,7 +908,7 @@ PaError Pa_OpenStream( PaStream** stream, @param stream The address of a PaStream pointer which will receive a pointer to the newly opened stream. - + @param numInputChannels The number of channels of sound that will be supplied to the stream callback or returned by Pa_ReadStream. It can range from 1 to the value of maxInputChannels in the PaDeviceInfo record for the default input @@ -913,13 +917,13 @@ PaError Pa_OpenStream( PaStream** stream, @param numOutputChannels The number of channels of sound to be delivered to the stream callback or passed to Pa_WriteStream. It can range from 1 to the value of maxOutputChannels in the PaDeviceInfo record for the default output device. - If 0 the stream is opened as an output-only stream. + If 0 the stream is opened as an input-only stream. @param sampleFormat The sample format of both the input and output buffers provided to the callback or passed to and from Pa_ReadStream and Pa_WriteStream. sampleFormat may be any of the formats described by the PaSampleFormat enumeration. - + @param sampleRate Same as Pa_OpenStream parameter of the same name. @param framesPerBuffer Same as Pa_OpenStream parameter of the same name. @param streamCallback Same as Pa_OpenStream parameter of the same name. @@ -945,7 +949,7 @@ PaError Pa_OpenDefaultStream( PaStream** stream, PaError Pa_CloseStream( PaStream *stream ); -/** Functions of type PaStreamFinishedCallback are implemented by PortAudio +/** Functions of type PaStreamFinishedCallback are implemented by PortAudio clients. They can be registered with a stream using the Pa_SetStreamFinishedCallback function. Once registered they are called when the stream becomes inactive (ie once a call to Pa_StopStream() will not block). @@ -954,7 +958,7 @@ PaError Pa_CloseStream( PaStream *stream ); output, if the stream callback returns paComplete, or Pa_StopStream() is called, the stream finished callback will not be called until all generated sample data has been played. - + @param userData The userData parameter supplied to Pa_OpenStream() @see Pa_SetStreamFinishedCallback @@ -962,12 +966,12 @@ PaError Pa_CloseStream( PaStream *stream ); typedef void PaStreamFinishedCallback( void *userData ); -/** Register a stream finished callback function which will be called when the - stream becomes inactive. See the description of PaStreamFinishedCallback for +/** Register a stream finished callback function which will be called when the + stream becomes inactive. See the description of PaStreamFinishedCallback for further details about when the callback will be called. @param stream a pointer to a PaStream that is in the stopped state - if the - stream is not stopped, the stream's finished callback will remain unchanged + stream is not stopped, the stream's finished callback will remain unchanged and an error code will be returned. @param streamFinishedCallback a pointer to a function with the same signature @@ -980,7 +984,7 @@ typedef void PaStreamFinishedCallback( void *userData ); @see PaStreamFinishedCallback */ -PaError Pa_SetStreamFinishedCallback( PaStream *stream, PaStreamFinishedCallback* streamFinishedCallback ); +PaError Pa_SetStreamFinishedCallback( PaStream *stream, PaStreamFinishedCallback* streamFinishedCallback ); /** Commences audio processing. @@ -1065,7 +1069,7 @@ typedef struct PaStreamInfo parameter passed to Pa_OpenStream(). */ double sampleRate; - + } PaStreamInfo; @@ -1087,15 +1091,15 @@ const PaStreamInfo* Pa_GetStreamInfo( PaStream *stream ); /** Returns the current time in seconds for a stream according to the same clock used to generate callback PaStreamCallbackTimeInfo timestamps. The time values are - monotonically increasing and have unspecified origin. - + monotonically increasing and have unspecified origin. + Pa_GetStreamTime returns valid time values for the entire life of the stream, from when the stream is opened until it is closed. Starting and stopping the stream does not affect the passage of time returned by Pa_GetStreamTime. - This time may be used for synchronizing other events to the audio stream, for + This time may be used for synchronizing other events to the audio stream, for example synchronizing audio to MIDI. - + @return The stream's current time in seconds, or 0 if an error occurred. @see PaTime, PaStreamCallback, PaStreamCallbackTimeInfo @@ -1110,7 +1114,7 @@ PaTime Pa_GetStreamTime( PaStream *stream ); This function may be called from the stream callback function or the application. - + @return A floating point value, typically between 0.0 and 1.0, where 1.0 indicates that the stream callback is consuming the maximum number of CPU cycles possible @@ -1126,13 +1130,17 @@ double Pa_GetStreamCpuLoad( PaStream* stream ); the entire buffer has been filled - this may involve waiting for the operating system to supply the data. + Reading from a stream that is stopped is not currently supported. In particular, + it is not possible to drain the read buffer by calling Pa_ReadStream after + calling Pa_StopStream. + @param stream A pointer to an open stream previously created with Pa_OpenStream. - + @param buffer A pointer to a buffer of sample frames. The buffer contains samples in the format specified by the inputParameters->sampleFormat field used to open the stream, and the number of channels specified by inputParameters->numChannels. If non-interleaved samples were requested using - the paNonInterleaved sample format flag, buffer is a pointer to the first element + the paNonInterleaved sample format flag, buffer is a pointer to the first element of an array of buffer pointers, one non-interleaved buffer for each channel. @param frames The number of frames to be read into buffer. This parameter @@ -1152,13 +1160,17 @@ PaError Pa_ReadStream( PaStream* stream, entire buffer has been written - this may involve waiting for the operating system to consume the data. + Writing to a stream that is stopped is not currently supported. In particular, + it is not possible to prefill the write buffer by calling Pa_WriteStream + prior to calling Pa_StartStream. + @param stream A pointer to an open stream previously created with Pa_OpenStream. @param buffer A pointer to a buffer of sample frames. The buffer contains samples in the format specified by the outputParameters->sampleFormat field used to open the stream, and the number of channels specified by outputParameters->numChannels. If non-interleaved samples were requested using - the paNonInterleaved sample format flag, buffer is a pointer to the first element + the paNonInterleaved sample format flag, buffer is a pointer to the first element of an array of buffer pointers, one non-interleaved buffer for each channel. @param frames The number of frames to be written from buffer. This parameter @@ -1178,6 +1190,9 @@ PaError Pa_WriteStream( PaStream* stream, /** Retrieve the number of frames that can be read from the stream without waiting. + When the stream is stopped the return value of Pa_GetStreamReadAvailable is not + defined. + @return Returns a non-negative value representing the maximum number of frames that can be read from the stream without blocking or busy waiting or, a PaErrorCode (which are always negative) if PortAudio is not initialized or an @@ -1189,6 +1204,9 @@ signed long Pa_GetStreamReadAvailable( PaStream* stream ); /** Retrieve the number of frames that can be written to the stream without waiting. + When the stream is stopped the return value of Pa_GetStreamWriteAvailable is not + defined. + @return Returns a non-negative value representing the maximum number of frames that can be written to the stream without blocking or busy waiting or, a PaErrorCode (which are always negative) if PortAudio is not initialized or an diff --git a/3rdparty/portaudio/ltmain.sh b/3rdparty/portaudio/ltmain.sh index a356acafa45..4a1ede7111e 100644 --- a/3rdparty/portaudio/ltmain.sh +++ b/3rdparty/portaudio/ltmain.sh @@ -189,7 +189,7 @@ func_basename () # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. -# value retuned in "$func_basename_result" +# value returned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. @@ -602,7 +602,7 @@ func_quote_for_eval () case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay - # word splitting, command substitution and and variable + # word splitting, command substitution and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. @@ -4394,7 +4394,7 @@ EOF { /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX namespace, but it is not one of the ones we know about and - have already dealt with, above (inluding dump-script), then + have already dealt with, above (including dump-script), then report an error. Otherwise, targets might begin to believe they are allowed to use options in the LTWRAPPER_OPTION_PREFIX namespace. The first time any user complains about this, we'll diff --git a/3rdparty/portaudio/msvc/portaudio.def b/3rdparty/portaudio/msvc/portaudio.def new file mode 100644 index 00000000000..e0ee67f968f --- /dev/null +++ b/3rdparty/portaudio/msvc/portaudio.def @@ -0,0 +1,64 @@ +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 +Pa_GetVersionInfo @35 +PaAsio_GetAvailableBufferSizes @50 +PaAsio_ShowControlPanel @51 +PaUtil_InitializeX86PlainConverters @52 +PaAsio_GetInputChannelName @53 +PaAsio_GetOutputChannelName @54 +PaUtil_SetDebugPrintFunction @55 +PaWasapi_GetAudioClient @56 +PaWasapi_UpdateDeviceList @57 +PaWasapi_GetDeviceCurrentFormat @58 +PaWasapi_GetDeviceDefaultFormat @59 +PaWasapi_GetDeviceMixFormat @60 +PaWasapi_GetDeviceRole @61 +PaWasapi_ThreadPriorityBoost @62 +PaWasapi_ThreadPriorityRevert @63 +PaWasapi_GetFramesPerHostBuffer @64 +PaWasapi_GetJackCount @65 +PaWasapi_GetJackDescription @66 +PaWasapi_SetStreamStateHandler @68 +PaWasapiWinrt_SetDefaultDeviceId @67 +PaWasapiWinrt_PopulateDeviceList @69 +PaWasapi_GetIMMDevice @70 +PaWasapi_IsLoopback @71 +PaWinMME_GetStreamInputHandleCount @72 +PaWinMME_GetStreamInputHandle @73 +PaWinMME_GetStreamOutputHandleCount @74 +PaWinMME_GetStreamOutputHandle @75 \ No newline at end of file diff --git a/3rdparty/portaudio/msvc/portaudio.dsp b/3rdparty/portaudio/msvc/portaudio.dsp new file mode 100644 index 00000000000..bfe1437cd9d --- /dev/null +++ b/3rdparty/portaudio/msvc/portaudio.dsp @@ -0,0 +1,269 @@ +# Microsoft Developer Studio Project File - Name="portaudio" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=portaudio - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "portaudio.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "portaudio.mak" CFG="portaudio - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "portaudio - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "portaudio - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "portaudio - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release_x86" +# PROP BASE Intermediate_Dir "Release_x86" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release_x86" +# PROP Intermediate_Dir "Release_x86" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\src\common" /I "..\..\include" /I ".\\" /I "..\..\src\os\win" /D "WIN32" /D "NDEBUG" /D "_USRDLL" /D "PA_ENABLE_DEBUG_OUTPUT" /D "_CRT_SECURE_NO_DEPRECATE" /D "PAWIN_USE_WDMKS_DEVICE_INFO" /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setupapi.lib /nologo /dll /machine:I386 /out:"./Release_x86/portaudio_x86.dll" + +!ELSEIF "$(CFG)" == "portaudio - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug_x86" +# PROP BASE Intermediate_Dir "Debug_x86" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug_x86" +# PROP Intermediate_Dir "Debug_x86" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\src\common" /I "..\..\include" /I ".\\" /I "..\..\src\os\win" /D "WIN32" /D "_DEBUG" /D "_USRDLL" /D "PA_ENABLE_DEBUG_OUTPUT" /D "_CRT_SECURE_NO_DEPRECATE" /D "PAWIN_USE_WDMKS_DEVICE_INFO" /FD /GZ /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setupapi.lib /nologo /dll /debug /machine:I386 /out:"./Debug_x86/portaudio_x86.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "portaudio - Win32 Release" +# Name "portaudio - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\src\common\pa_allocation.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_converters.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_cpuload.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_debugprint.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_dither.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_front.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_process.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_ringbuffer.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\skeleton\pa_hostapi_skeleton.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\common\pa_stream.c +# End Source File +# End Group +# Begin Group "hostapi" + +# PROP Default_Filter "" +# Begin Group "ASIO" + +# PROP Default_Filter "" +# Begin Group "ASIOSDK" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\ASIOSDK\common\asio.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\ASIOSDK\host\ASIOConvertSamples.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\ASIOSDK\host\asiodrivers.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\ASIOSDK\host\pc\asiolist.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\ASIOSDK\common\combase.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\ASIOSDK\common\debugmessage.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\ASIOSDK\common\register.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\src\hostapi\asio\pa_asio.cpp +# ADD CPP /I "..\..\src\hostapi\asio\ASIOSDK\host" /I "..\..\src\hostapi\asio\ASIOSDK\host\pc" /I "..\..\src\hostapi\asio\ASIOSDK\common" +# End Source File +# End Group +# Begin Group "dsound" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\src\hostapi\dsound\pa_win_ds.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\hostapi\dsound\pa_win_ds_dynlink.c +# End Source File +# End Group +# Begin Group "wmme" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\src\hostapi\wmme\pa_win_wmme.c +# End Source File +# End Group +# Begin Group "wasapi" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\src\hostapi\wasapi\pa_win_wasapi.cpp +# End Source File +# End Group +# Begin Group "wdm-ks" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\src\hostapi\wdmks\pa_win_wdmks.c +# End Source File +# End Group +# End Group +# Begin Group "os" + +# PROP Default_Filter "" +# Begin Group "win" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\src\os\win\pa_win_hostapis.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\os\win\pa_win_util.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\os\win\pa_win_waveformat.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\os\win\pa_win_wdmks_utils.c +# End Source File +# Begin Source File + +SOURCE=..\..\src\os\win\pa_x86_plain_converters.c +# End Source File +# End Group +# End Group +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\portaudio.def +# End Source File +# End Group +# End Target +# End Project diff --git a/3rdparty/portaudio/msvc/portaudio.dsw b/3rdparty/portaudio/msvc/portaudio.dsw new file mode 100644 index 00000000000..58d0ea9fb1c --- /dev/null +++ b/3rdparty/portaudio/msvc/portaudio.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "portaudio"=".\portaudio.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/3rdparty/portaudio/msvc/portaudio.sln b/3rdparty/portaudio/msvc/portaudio.sln new file mode 100644 index 00000000000..ef9456e066f --- /dev/null +++ b/3rdparty/portaudio/msvc/portaudio.sln @@ -0,0 +1,32 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "portaudio", "portaudio.vcproj", "{0A18A071-125E-442F-AFF7-A3F68ABECF99}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseMinDependency|Win32 = ReleaseMinDependency|Win32 + ReleaseMinDependency|x64 = ReleaseMinDependency|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.ActiveCfg = Debug|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.Build.0 = Debug|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.ActiveCfg = Debug|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.Build.0 = Debug|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|Win32.ActiveCfg = Release|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|Win32.Build.0 = Release|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64.ActiveCfg = Release|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64.Build.0 = Release|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.ReleaseMinDependency|Win32.ActiveCfg = ReleaseMinDependency|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.ReleaseMinDependency|Win32.Build.0 = ReleaseMinDependency|Win32 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.ReleaseMinDependency|x64.ActiveCfg = ReleaseMinDependency|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.ReleaseMinDependency|x64.Build.0 = ReleaseMinDependency|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/3rdparty/portaudio/msvc/portaudio.vcproj b/3rdparty/portaudio/msvc/portaudio.vcproj new file mode 100644 index 00000000000..0eb6321dfa1 --- /dev/null +++ b/3rdparty/portaudio/msvc/portaudio.vcproj @@ -0,0 +1,1932 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3rdparty/portaudio/msvc/readme.txt b/3rdparty/portaudio/msvc/readme.txt new file mode 100644 index 00000000000..07421ff2d06 --- /dev/null +++ b/3rdparty/portaudio/msvc/readme.txt @@ -0,0 +1,112 @@ +Hello + + This is a small list of steps in order to build portaudio +(Currently v19-devel) into a VS2005 DLL and lib file. +This DLL contains all 5 current Win32 PA APIS (MME/DS/ASIO/WASAPI/WDMKS) + +1)Copy the source dirs that comes with the ASIO SDK inside src\hostapi\asio\ASIOSDK + so you should now have example: + + portaudio19svn\src\hostapi\asio\ASIOSDK\common + portaudio19svn\src\hostapi\asio\ASIOSDK\host + portaudio19svn\src\hostapi\asio\ASIOSDK\host\sample + portaudio19svn\src\hostapi\asio\ASIOSDK\host\pc + portaudio19svn\src\hostapi\asio\ASIOSDK\host\mac (not needed) + + You dont need "driver" + + To build without ASIO (or another Host API) see the "Building without ASIO support" section below. + +2) + *If you have Visual Studio 6.0*, please make sure you have it updated with the latest (and final) + microsoft libraries for it, namely: + + Service pack 5: + Latest known URL: + http://msdn2.microsoft.com/en-us/vstudio/aa718363.aspx + Yes there EXISTS a service pack 6 , but the processor pack (below) isn't compatible with it. + + Processor Pack(only works with above SP5) + Latest known URL: + http://msdn2.microsoft.com/en-us/vstudio/Aa718349.aspx + This isn't absolutely required for portaudio, but if you plan on using SSE intrinsics and similar things. + Up to you to decide upon Service pack 5 or 6 depending on your need for intrinsics. + + Platform SDK (Feb 2003) : + Latest known URL: + http://www.microsoft.com/msdownload/platformsdk/sdkupdate/psdk-full.htm + (This will allow your code base to be x64 friendly, with correct defines + for LONG_PTR and such) + NOTE A) Yes you have to use IE activex scripts to install that - wont work in Firefox, you + may have to temporarily change tyour default browser(aint life unfair) + NOTE B) Dont forget to hit "Register PSDK Directories with Visual Studio". + you can make sure its right in VC6 if you open tools/options/directories/include files and you see SDK 2003 as the FIRST entry + (it must be the same for libs) + + DirectX 9.0 SDK Update - (Summer 2003) + Latest known URL: + http://www.microsoft.com/downloads/details.aspx?familyid=9216652f-51e0-402e-b7b5-feb68d00f298&displaylang=en + Again register the links in VC6, and check inside vc6 if headers are in second place right after SDk 2003 + + *If you have 7.0(VC.NET/2001) or 7.1(VC.2003) * + then I suggest you open portaudio.dsp (and convert if needed) + + *If you have Visual Studio 2005 * (or later), I suggest you open the portaudio.sln file + which contains 2 projects (portaudio & portaudio_static) each with 6 configurations: Win32/x64 in both Debug, Release and ReleaseMinDependency, + last of which removes dependency of all but basic OS system DLLs. + + hit compile and hope for the best. + +3)Now in any project, in which you require portaudio, + you can just link with portaudio_x86.lib, (or _x64) and of course include the + relevant headers + (portaudio.h, and/or pa_asio.h , pa_x86_plain_converters.h) See (*) + +4) Your new exe should now use portaudio_xXX.dll. + + +Have fun! + +(*): you may want to add/remove some DLL entry points. +Right now those 6 entries are _not_ from portaudio.h + +(from portaudio.def) +(...) +PaAsio_GetAvailableLatencyValues @50 +PaAsio_ShowControlPanel @51 +PaUtil_InitializeX86PlainConverters @52 +PaAsio_GetInputChannelName @53 +PaAsio_GetOutputChannelName @54 +PaUtil_SetLogPrintFunction @55 + + +*** Building without ASIO support *** + +To build PortAudio without ASIO support you need to: + A. Make sure your project doesn't try to build any ASIO SDK files. + If you're using one of the shipped projects, remove the ASIO related files + from the project. + + B. Make sure your project doesn't try to build the PortAudio ASIO + implementation files: + src/hostapi/pa_asio.cpp + src/hostapi/iasiothiscallresolver.cpp + If you're using one of the shipped projects remove them from the project. + + C. Set the PA_USE_ASIO preprocessor symbol to zero (i.e. PA_USE_ASIO=0) in the project properties. + In VS2005 this can be added under + Project Properties > Configuration Properties > C/C++ > Preprocessor > Preprocessor Definitions + + Setting PA_USE_ASIO=0 stops src/os/win/pa_win_hostapis.c + from trying to initialize the PA ASIO implementation. + + D. Remove PaAsio_* entry points from portaudio.def, or comment them out with ; + + +A similar procedure can be used to omit any of the other host APIs from the +build. The relevant preprocessor symbols used by pa_win_hostapis.c are: +PA_USE_WMME, PA_USE_DSOUND, PA_USE_ASIO, PA_USE_WASAPI and PA_USE_WDMKS + +----- +David Viens, davidv@plogue.com +Robert Bielik, robert@xponaut.se diff --git a/3rdparty/portaudio/pa_compare_def_files.py b/3rdparty/portaudio/pa_compare_def_files.py new file mode 100644 index 00000000000..d8becabc613 --- /dev/null +++ b/3rdparty/portaudio/pa_compare_def_files.py @@ -0,0 +1,98 @@ +# PortAudio Repository .def file checker +# +# Run this script from the root of the repository using the command: +# python pa_compare_def_files.py +# +# The PortAudio repository contains two (semi-redundant) .def +# files that specify exported symbols for Windows dynamic link libraries. +# +# This script checks that the two .def files export the same symbols +# using the same ordinals. +# +# The .def files are: +# +# 1. msvc/portaudio.def +# 2. cmake/portaudio.def.in +# +# The CMake .def.in file is an input that generates a .def file +# with host-api-specific symbols commented out when a particular host API +# is not built. + +import sys + +msvc_portaudio_def_path = "msvc/portaudio.def" +cmake_portaudio_def_in_path = "cmake/portaudio.def.in" + +def parse_def_file(file): + result = {} + for line in file: + line = line.strip() + if line: + if "EXPORTS" in line or line[0] == ";": + continue + columns = line.split() + #print(columns) + symbol, ordinal = columns + #print(symbol, ordinal) + if ordinal in result: + print(f"error: ordinal {ordinal} referenced multiple times") + result[ordinal] = symbol + return result + +with open(msvc_portaudio_def_path, mode="rt", encoding="utf-8") as msvc_portaudio_def: + msvc_portaudio_def_syms = parse_def_file(msvc_portaudio_def) + +with open(cmake_portaudio_def_in_path, mode="rt", encoding="utf-8") as cmake_portaudio_def_in: + cmake_portaudio_def_in_syms = parse_def_file(cmake_portaudio_def_in) + +def clear_cmake_exclude_condition_prefix(sym): + if "@" in sym: + return sym.split("@")[-1] + else: + return sym + +# dictionary keys are the ordinals +ordinals = list(set(msvc_portaudio_def_syms.keys()).union(cmake_portaudio_def_in_syms.keys())) +ordinals.sort(key=lambda s: int(s.replace("@", ""))) + +msvcMissingCount = 0 +cmakeMissingCount = 0 +differenceCount = 0 + +print("ordinal, msvc, cmake, remark") +for ordinal in ordinals: + msvc_sym = msvc_portaudio_def_syms[ordinal] if ordinal in msvc_portaudio_def_syms else "" + cmake_sym = cmake_portaudio_def_in_syms[ordinal] if ordinal in cmake_portaudio_def_in_syms else "" + + cmake_sym_no_cond = clear_cmake_exclude_condition_prefix(cmake_sym) + + remark = "" + if not msvc_sym: + remark = "missing in msvc/portaudio.def" + msvcMissingCount += msvcMissingCount + elif not cmake_sym: + remark = "missing in cmake/portaudio.def.in" + cmakeMissingCount += cmakeMissingCount + elif msvc_sym != cmake_sym_no_cond: + remark = "differs" + differenceCount += 1 + else: + remark = "ok" + + print(f"{ordinal}, {msvc_sym}, {cmake_sym}, {remark}") + +print("SUMMARY") +print("=======") +issuesFound = msvcMissingCount > 0 or cmakeMissingCount > 0 or differenceCount > 0 +if msvcMissingCount > 0: + print(f"error: {msvc_portaudio_def_path} ({msvcMissingCount} missing symbols)") +if cmakeMissingCount > 0: + print(f"error: {cmake_portaudio_def_in_path} ({cmakeMissingCount} missing symbols)") +if differenceCount > 0: + print(f"error: there are {differenceCount} ordinals with non-matching symbols") + +if issuesFound: + sys.exit(1) +else: + print("No issues found. All good.") + sys.exit(0) diff --git a/3rdparty/portaudio/pa_whitelint.py b/3rdparty/portaudio/pa_whitelint.py new file mode 100644 index 00000000000..fe47ad1d679 --- /dev/null +++ b/3rdparty/portaudio/pa_whitelint.py @@ -0,0 +1,297 @@ +# PortAudio Repository Whitespace Linter +# +# Run this script from the root of the repository using the command: +# python pa_whitelint.py +# +# Check all source files for the following: +# 1. Consistent line endings are used throughout each file. +# 2. No tabs are present. Use spaces for indenting. +# 3. Indenting: leading whitespace is usually a multiple of 4 spaces, +# with permissive exceptions for continuation lines. +# 4. Lines have no trailing whitespace. +# 5. No non-ASCII or weird control characters are present. +# 6. End-of-line is present at end-of-file. +# 7. No empty (or whitespace) lines at end-of-file. + + +from pathlib import Path +import re +import sys + +# Configuration: + +# Check these file types: +sourceFileTypes = ["*.c", "*.h", "*.cpp", "*.cxx", "*.hxx"] + +# Scan these directories +dirs = ["src", "include", "examples", "test", "qa"] + +# Exclude files or directories with the following names: +excludePathParts = [ + "ASIOSDK", + "iasiothiscallresolver.cpp", + "iasiothiscallresolver.h", + "mingw-include", +] + +indentSpaceCount = 4 + +verbose = True +checkBadIndenting = True +verboseBadIndenting = True + +# (End configuration) + + +class FileStatus: + """Issue status for a particular file. Stores issue counts for each type of issue.""" + + def __init__(self, path): + self.path = path + issueNames = [ + "has-inconsistent-line-endings", + "has-tabs", + "has-bad-indenting", + "has-trailing-whitespace", + "has-bad-character", + "has-empty-line-at-end-of-file", + "has-no-eol-character-at-end-of-file", + ] + self.issueCounts = dict.fromkeys(issueNames, 0) + + def incrementIssueCount(self, issueName): + assert issueName in self.issueCounts # catch typos in issueName + self.issueCounts[issueName] += 1 + + def hasIssue(self, issueName): + return self.issueCounts[issueName] > 0 + + def hasIssues(self): + return any(count > 0 for count in self.issueCounts.values()) + + def issueSummaryString(self): + return str.join(", ", [name for name in self.issueCounts if self.issueCounts[name] > 0]) + + +def multilineCommentIsOpenAtEol(lineText, wasOpenAtStartOfLine): + isOpen = wasOpenAtStartOfLine + index = 0 + end = len(lineText) + while index != -1 and index < end: + if isOpen: + index = lineText.find(b"*/", index) + if index != -1: + isOpen = False + index += 2 + else: + index = lineText.find(b"/*", index) + if index != -1: + isOpen = True + index += 2 + return isOpen + + +def allowStrangeIndentOnFollowingLine(lineText): + """Compute whether a non-standard indent is allowed on the following line. + A line allows an unusual indent to follow if it is the beginning of a + multi-line function parameter list, an element of a function parameter list, + or an incomplete expression (binary operator, etc.). + """ + s = lineText.strip(b" ") + if len(s) == 0: + return False + if s.rfind(b"*/") == (len(s) - 2): # line has a trailing comment, strip it + commentStart = s.rfind(b"/*") + if commentStart != -1: + s = s[:commentStart].strip(b" ") + if len(s) == 0: + return False + + if len(s) == 0: + return False + + okChars = b'(,\\+-/*=&|?:"' + if s[-1] in okChars: # non-comment program text has trailing okChar: '(' or ',' etc. + return True + return False + + +def allowStrangeIndentOfLine(lineText): + """Compute whether a non-standard indent is allowed on the line. + A line is allowed an unusual indent if it is the continuation of an + incomplete expression (binary operator, etc.). + """ + s = lineText.strip(b" ") + if len(s) == 0: + return False + + okChars = b'+-/*=&|?:)"' + if s[0] in okChars: + return True + return False + + +# Run the checks over all files specified by [sourceFileTypes, dirs, excludePathParts]: + +statusSummary = [] +for dir in dirs: + for ext in sourceFileTypes: + for path in Path(dir).rglob(ext): + if any(part in path.parts for part in excludePathParts): + continue + + # during development, uncomment the following 2 lines and select a specific path: + #if not "qa" in path.parts: + # continue + + data = path.read_bytes() + + status = FileStatus(path) + statusSummary.append(status) + + # Perform checks: + + # 1. Consistent line endings + # check and then normalize to \n line endings for the benefit of the rest of the program + if b"\r" in data and b"\n" in data: + # CRLF (Windows) case: check for stray CR or LF, then convert CRLF to LF + assert not b"\f" in data # we'll use \f as a sentinel during conversion + d = data.replace(b"\r\n", b"\f") + if b"\r" in d: + status.incrementIssueCount("has-inconsistent-line-endings") + if verbose: + print("error: {0} stray carriage return".format(path)) + if b"\n" in d: + status.incrementIssueCount("has-inconsistent-line-endings") + if verbose: + print("error: {0} stray newline".format(path)) + data = d.replace(b"\f", b"\n") # normalize line endings + elif b"\r" in data: + # CR (Classic Mac) case: convert CR to LF + data = d.replace(b"\r", b"\n") # normalize line endings + else: + # LF (Unix) case: no change + pass + + lines = data.split(b"\n") # relies on newline normalization above + + # 2. Absence of tabs + lineNo = 1 + for line in lines: + if b"\t" in line: + status.incrementIssueCount("has-tabs") + if verbose: + print("error: {0}({1}) contains tab".format(path, lineNo)) + lineNo += 1 + + data = data.replace(b"\t", b" "*indentSpaceCount) # normalize tabs to spaces for indent algorithm below + lines = data.split(b"\n") # recompute lines, relies on newline normalization above + + # 3. Correct leading whitespace / bad indenting + if checkBadIndenting: + leadingWhitespaceRe = re.compile(b"^\s*") + commentIsOpen = False + previousLine = b"" + previousIndent = 0 + lineNo = 1 + for line in lines: + if commentIsOpen: + # don't check leading whitespace inside comments + commentIsOpen = multilineCommentIsOpenAtEol(line, commentIsOpen) + previousIndent = 0 + else: + m = leadingWhitespaceRe.search(line) + indent = m.end() - m.start() + if indent != len(line): # ignore whitespace lines, they are considered trailing whitespace + if indent % indentSpaceCount != 0 and indent != previousIndent: + # potential bad indents are not multiples of , + # and are not indented the same as the previous line + s = previousLine + if not allowStrangeIndentOnFollowingLine(previousLine) and not allowStrangeIndentOfLine(line): + status.incrementIssueCount("has-bad-indenting") + if verbose or verboseBadIndenting: + print("error: {0}({1}) bad indent: {2}".format(path, lineNo, indent)) + print(line) + commentIsOpen = multilineCommentIsOpenAtEol(line, commentIsOpen) + previousIndent = indent + previousLine = line + lineNo += 1 + + # 4. No trailing whitespace + trailingWhitespaceRe = re.compile(b"\s*$") + lineNo = 1 + for line in lines: + m = trailingWhitespaceRe.search(line) + trailing = m.end() - m.start() + if trailing > 0: + status.incrementIssueCount("has-trailing-whitespace") + if verbose: + print("error: {0}({1}) trailing whitespace:".format(path, lineNo)) + print(line) + lineNo += 1 + + # 5. No non-ASCII or weird control characters + badCharactersRe = re.compile(b"[^\t\r\n\x20-\x7E]+") + lineNo = 1 + for line in lines: + m = badCharactersRe.search(line) + if m: + bad = m.end() - m.start() + if bad > 0: + status.incrementIssueCount("has-bad-character") + if verbose: + print("error: {0}({1}) bad character:".format(path, lineNo)) + print(line) + lineNo += 1 + + # 6. Require EOL at EOF + if len(data) == 0: + status.incrementIssueCount("has-no-eol-character-at-end-of-file") + if verbose: + lineNo = 1 + print("error: {0}({1}) no end-of-line at end-of-file (empty file)".format(path, lineNo)) + else: + lastChar = data[-1] + if lastChar != b"\n"[0]: + status.incrementIssueCount("has-no-eol-character-at-end-of-file") + if verbose: + lineNo = len(lines) + print("error: {0}({1}) no end-of-line at end-of-file".format(path, lineNo)) + + # 7. No "empty" (or whitespace) lines at end-of-file. + # Cases: + # 1. There is an EOL at EOF. Since the lines array is constructed by splitting on '\n', + # the final element in the lines array will be an empty string. This is expeced and allowed. + # Then continue to check for earlier empty lines. + # 2. There is no EOF at EOL. + # Check for empty lines, including the final line. + expectEmptyFinalLine = not status.hasIssue("has-no-eol-character-at-end-of-file") # i.e. we have EOL at EOF + finalLineNo = len(lines) + lineNo = finalLineNo + for line in reversed(lines): + if lineNo == finalLineNo and expectEmptyFinalLine: + assert len(line) == 0 # this is guaranteed, since lines = data.split('\n') and there is an EOL at EOF + else: + s = line.strip(b" ") # whitespace-only-lines count as empty + if len(s) == 0: + status.incrementIssueCount("has-empty-line-at-end-of-file") + if verbose: + print("error: {0}({1}) empty line at end-of-file".format(path, lineNo)) + else: + break # stop checking once we encounter a non-empty line + lineNo -= 1 + + +print("SUMMARY") +print("=======") +issuesFound = False +for s in statusSummary: + if s.hasIssues(): + issuesFound = True + print("error: " + str(s.path) + " (" + s.issueSummaryString() + ")") + +if issuesFound: + sys.exit(1) +else: + print("all good.") + sys.exit(0) diff --git a/3rdparty/portaudio/qa/CMakeLists.txt b/3rdparty/portaudio/qa/CMakeLists.txt new file mode 100644 index 00000000000..6577c980c55 --- /dev/null +++ b/3rdparty/portaudio/qa/CMakeLists.txt @@ -0,0 +1,5 @@ +add_test(paqa_devs) +add_test(paqa_errs) +add_test(paqa_latency) + +subdirs(loopback) diff --git a/3rdparty/portaudio/qa/loopback/CMakeLists.txt b/3rdparty/portaudio/qa/loopback/CMakeLists.txt new file mode 100644 index 00000000000..ca6408a9f29 --- /dev/null +++ b/3rdparty/portaudio/qa/loopback/CMakeLists.txt @@ -0,0 +1,19 @@ +add_executable(paloopback + src/audio_analyzer.c + src/audio_analyzer.h + src/biquad_filter.c + src/biquad_filter.h + src/paqa.c + src/paqa_tools.c + src/paqa_tools.h + src/qa_tools.h + src/test_audio_analyzer.c + src/test_audio_analyzer.h + src/write_wav.c + src/write_wav.h +) +target_include_directories(paloopback PRIVATE ..) +target_link_libraries(paloopback PortAudio) +if(UNIX) + target_link_libraries(paloopback m) +endif() diff --git a/3rdparty/portaudio/qa/loopback/src/audio_analyzer.c b/3rdparty/portaudio/qa/loopback/src/audio_analyzer.c index 0a3dbdf9232..fbdd6318205 100644 --- a/3rdparty/portaudio/qa/loopback/src/audio_analyzer.c +++ b/3rdparty/portaudio/qa/loopback/src/audio_analyzer.c @@ -26,13 +26,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -50,153 +50,153 @@ /*==========================================================================================*/ double PaQa_GetNthFrequency( double baseFrequency, int index ) { - // Use 13 tone equal tempered scale because it does not generate harmonic ratios. - return baseFrequency * pow( 2.0, index / 13.0 ); + // Use 13 tone equal tempered scale because it does not generate harmonic ratios. + return baseFrequency * pow( 2.0, index / 13.0 ); } /*==========================================================================================*/ void PaQa_EraseBuffer( float *buffer, int numFrames, int samplesPerFrame ) { - int i; - int numSamples = numFrames * samplesPerFrame; - for( i=0; iphase = 0.0; - generator->amplitude = amplitude; - generator->frequency = frequency; - generator->phaseIncrement = 2.0 * frequency * MATH_PI / frameRate; + generator->phase = 0.0; + generator->amplitude = amplitude; + generator->frequency = frequency; + generator->phaseIncrement = 2.0 * frequency * MATH_PI / frameRate; } /*==========================================================================================*/ void PaQa_MixSine( PaQaSineGenerator *generator, float *buffer, int numSamples, int stride ) { - int i; - for( i=0; iphase ) * generator->amplitude; - *buffer += value; // Mix with existing value. - buffer += stride; - // Advance phase and wrap around. - generator->phase += generator->phaseIncrement; - if (generator->phase > MATH_TWO_PI) - { - generator->phase -= MATH_TWO_PI; - } - } + int i; + for( i=0; iphase ) * generator->amplitude; + *buffer += value; // Mix with existing value. + buffer += stride; + // Advance phase and wrap around. + generator->phase += generator->phaseIncrement; + if (generator->phase > MATH_TWO_PI) + { + generator->phase -= MATH_TWO_PI; + } + } } /*==========================================================================================*/ void PaQa_GenerateCrackDISABLED( float *buffer, int numSamples, int stride ) { - int i; - int offset = numSamples/2; - for( i=0; ibuffer = (float*)malloc(numBytes); - QA_ASSERT_TRUE( "Allocate recording buffer.", (recording->buffer != NULL) ); - recording->maxFrames = maxFrames; recording->sampleRate = frameRate; - recording->numFrames = 0; - return 0; + int numBytes = maxFrames * sizeof(float); + recording->buffer = (float*)malloc(numBytes); + QA_ASSERT_TRUE( "Allocate recording buffer.", (recording->buffer != NULL) ); + recording->maxFrames = maxFrames; recording->sampleRate = frameRate; + recording->numFrames = 0; + return 0; error: - return 1; + return 1; } /*==========================================================================================*/ void PaQa_TerminateRecording( PaQaRecording *recording ) -{ - if (recording->buffer != NULL) - { - free( recording->buffer ); - recording->buffer = NULL; - } - recording->maxFrames = 0; +{ + if (recording->buffer != NULL) + { + free( recording->buffer ); + recording->buffer = NULL; + } + recording->maxFrames = 0; } /*==========================================================================================*/ int PaQa_WriteRecording( PaQaRecording *recording, float *buffer, int numFrames, int stride ) { - int i; - int framesToWrite; + int i; + int framesToWrite; float *data = &recording->buffer[recording->numFrames]; framesToWrite = numFrames; - if ((framesToWrite + recording->numFrames) > recording->maxFrames) - { - framesToWrite = recording->maxFrames - recording->numFrames; - } - - for( i=0; inumFrames += framesToWrite; - return (recording->numFrames >= recording->maxFrames); + if ((framesToWrite + recording->numFrames) > recording->maxFrames) + { + framesToWrite = recording->maxFrames - recording->numFrames; + } + + for( i=0; inumFrames += framesToWrite; + return (recording->numFrames >= recording->maxFrames); } /*==========================================================================================*/ int PaQa_WriteSilence( PaQaRecording *recording, int numFrames ) { - int i; - int framesToRecord; + int i; + int framesToRecord; float *data = &recording->buffer[recording->numFrames]; framesToRecord = numFrames; - if ((framesToRecord + recording->numFrames) > recording->maxFrames) - { - framesToRecord = recording->maxFrames - recording->numFrames; - } - - for( i=0; inumFrames += framesToRecord; - return (recording->numFrames >= recording->maxFrames); + if ((framesToRecord + recording->numFrames) > recording->maxFrames) + { + framesToRecord = recording->maxFrames - recording->numFrames; + } + + for( i=0; inumFrames += framesToRecord; + return (recording->numFrames >= recording->maxFrames); } /*==========================================================================================*/ int PaQa_RecordFreeze( PaQaRecording *recording, int numFrames ) { - int i; - int framesToRecord; + int i; + int framesToRecord; float *data = &recording->buffer[recording->numFrames]; framesToRecord = numFrames; - if ((framesToRecord + recording->numFrames) > recording->maxFrames) - { - framesToRecord = recording->maxFrames - recording->numFrames; - } - - for( i=0; inumFrames += framesToRecord; - return (recording->numFrames >= recording->maxFrames); + if ((framesToRecord + recording->numFrames) > recording->maxFrames) + { + framesToRecord = recording->maxFrames - recording->numFrames; + } + + for( i=0; inumFrames += framesToRecord; + return (recording->numFrames >= recording->maxFrames); } /*==========================================================================================*/ @@ -209,37 +209,37 @@ int PaQa_SaveRecordingToWaveFile( PaQaRecording *recording, const char *filename int result = 0; #define NUM_SAMPLES (200) short data[NUM_SAMPLES]; - const int samplesPerFrame = 1; + const int samplesPerFrame = 1; int numLeft = recording->numFrames; - float *buffer = &recording->buffer[0]; + float *buffer = &recording->buffer[0]; result = Audio_WAV_OpenWriter( &writer, filename, recording->sampleRate, samplesPerFrame ); if( result < 0 ) goto error; - - while( numLeft > 0 ) + + while( numLeft > 0 ) { - int i; + int i; int numToSave = (numLeft > NUM_SAMPLES) ? NUM_SAMPLES : numLeft; - // Convert double samples to shorts. - for( i=0; i 32767 ) ival = 32767; - else if( ival < -32768 ) ival = -32768; - data[i] = ival; - } - result = Audio_WAV_WriteShorts( &writer, data, numToSave ); + // Convert double samples to shorts. + for( i=0; i 32767 ) ival = 32767; + else if( ival < -32768 ) ival = -32768; + data[i] = ival; + } + result = Audio_WAV_WriteShorts( &writer, data, numToSave ); if( result < 0 ) goto error; - numLeft -= numToSave; + numLeft -= numToSave; } - + result = Audio_WAV_CloseWriter( &writer ); if( result < 0 ) goto error; - + return 0; - + error: printf("ERROR: result = %d\n", result ); return result; @@ -250,29 +250,29 @@ error: double PaQa_MeasureCrossingSlope( float *buffer, int numFrames ) { - int i; - double slopeTotal = 0.0; - int slopeCount = 0; - float previous; - double averageSlope = 0.0; - - previous = buffer[0]; - for( i=1; i 0.0) && (previous < 0.0) ) - { - double delta = current - previous; - slopeTotal += delta; - slopeCount += 1; - } - previous = current; - } - if( slopeCount > 0 ) - { - averageSlope = slopeTotal / slopeCount; - } - return averageSlope; + int i; + double slopeTotal = 0.0; + int slopeCount = 0; + float previous; + double averageSlope = 0.0; + + previous = buffer[0]; + for( i=1; i 0.0) && (previous < 0.0) ) + { + double delta = current - previous; + slopeTotal += delta; + slopeCount += 1; + } + previous = current; + } + if( slopeCount > 0 ) + { + averageSlope = slopeTotal / slopeCount; + } + return averageSlope; } /*==========================================================================================*/ @@ -285,63 +285,63 @@ double PaQa_MeasureCrossingSlope( float *buffer, int numFrames ) * */ double PaQa_MeasureSineAmplitudeBySlope( PaQaRecording *recording, - double frequency, double frameRate, - int startFrame, int numFrames ) + double frequency, double frameRate, + int startFrame, int numFrames ) { - float *buffer = &recording->buffer[startFrame]; - double measuredSlope = PaQa_MeasureCrossingSlope( buffer, numFrames ); - double unitySlope = sin( MATH_TWO_PI * frequency / frameRate ); - double estimatedAmplitude = measuredSlope / unitySlope; - return estimatedAmplitude; + float *buffer = &recording->buffer[startFrame]; + double measuredSlope = PaQa_MeasureCrossingSlope( buffer, numFrames ); + double unitySlope = sin( MATH_TWO_PI * frequency / frameRate ); + double estimatedAmplitude = measuredSlope / unitySlope; + return estimatedAmplitude; } /*==========================================================================================*/ double PaQa_CorrelateSine( PaQaRecording *recording, double frequency, double frameRate, - int startFrame, int numFrames, double *phasePtr ) + int startFrame, int numFrames, double *phasePtr ) { - double magnitude = 0.0; + double magnitude = 0.0; int numLeft = numFrames; - double phase = 0.0; - double phaseIncrement = 2.0 * MATH_PI * frequency / frameRate; - double sinAccumulator = 0.0; - double cosAccumulator = 0.0; - float *data = &recording->buffer[startFrame]; + double phase = 0.0; + double phaseIncrement = 2.0 * MATH_PI * frequency / frameRate; + double sinAccumulator = 0.0; + double cosAccumulator = 0.0; + float *data = &recording->buffer[startFrame]; QA_ASSERT_TRUE( "startFrame out of bounds", (startFrame < recording->numFrames) ); - QA_ASSERT_TRUE( "numFrames out of bounds", ((startFrame+numFrames) <= recording->numFrames) ); - - while( numLeft > 0 ) - { - double sample = (double) *data++; - sinAccumulator += sample * sin( phase ); - cosAccumulator += sample * cos( phase ); - phase += phaseIncrement; - if (phase > MATH_TWO_PI) - { - phase -= MATH_TWO_PI; - } - numLeft -= 1; - } - sinAccumulator = sinAccumulator / numFrames; - cosAccumulator = cosAccumulator / numFrames; - // TODO Why do I have to multiply by 2.0? Need it to make result come out right. - magnitude = 2.0 * sqrt( (sinAccumulator * sinAccumulator) + (cosAccumulator * cosAccumulator )); - if( phasePtr != NULL ) - { - double phase = atan2( cosAccumulator, sinAccumulator ); - *phasePtr = phase; - } - return magnitude; + QA_ASSERT_TRUE( "numFrames out of bounds", ((startFrame+numFrames) <= recording->numFrames) ); + + while( numLeft > 0 ) + { + double sample = (double) *data++; + sinAccumulator += sample * sin( phase ); + cosAccumulator += sample * cos( phase ); + phase += phaseIncrement; + if (phase > MATH_TWO_PI) + { + phase -= MATH_TWO_PI; + } + numLeft -= 1; + } + sinAccumulator = sinAccumulator / numFrames; + cosAccumulator = cosAccumulator / numFrames; + // TODO Why do I have to multiply by 2.0? Need it to make result come out right. + magnitude = 2.0 * sqrt( (sinAccumulator * sinAccumulator) + (cosAccumulator * cosAccumulator )); + if( phasePtr != NULL ) + { + double phase = atan2( cosAccumulator, sinAccumulator ); + *phasePtr = phase; + } + return magnitude; error: - return -1.0; + return -1.0; } /*==========================================================================================*/ void PaQa_FilterRecording( PaQaRecording *input, PaQaRecording *output, BiquadFilter *filter ) { - int numToFilter = (input->numFrames > output->maxFrames) ? output->maxFrames : input->numFrames; - BiquadFilter_Filter( filter, &input->buffer[0], &output->buffer[0], numToFilter ); - output->numFrames = numToFilter; + int numToFilter = (input->numFrames > output->maxFrames) ? output->maxFrames : input->numFrames; + BiquadFilter_Filter( filter, &input->buffer[0], &output->buffer[0], numToFilter ); + output->numFrames = numToFilter; } /*==========================================================================================*/ @@ -351,92 +351,92 @@ void PaQa_FilterRecording( PaQaRecording *input, PaQaRecording *output, BiquadFi */ double PaQa_FindFirstMatch( PaQaRecording *recording, float *buffer, int numFrames, double threshold ) { - int ic,is; - // How many buffers will fit in the recording? - int maxCorrelations = recording->numFrames - numFrames; - double maxSum = 0.0; - int peakIndex = -1; - double inverseMaxSum = 0.0; - int inversePeakIndex = -1; - double location = -1.0; + int ic,is; + // How many buffers will fit in the recording? + int maxCorrelations = recording->numFrames - numFrames; + double maxSum = 0.0; + int peakIndex = -1; + double inverseMaxSum = 0.0; + int inversePeakIndex = -1; + double location = -1.0; QA_ASSERT_TRUE( "numFrames out of bounds", (numFrames < recording->numFrames) ); - for( ic=0; icbuffer[ ic ]; - for( is=0; is maxSum) ) - { - maxSum = sum; - peakIndex = ic; - } - if( ((-sum) > inverseMaxSum) ) - { - inverseMaxSum = -sum; - inversePeakIndex = ic; - } - pastPeak = (maxSum > threshold) && (sum < 0.5*maxSum); - inversePastPeak = (inverseMaxSum > threshold) && ((-sum) < 0.5*inverseMaxSum); - //printf("PaQa_FindFirstMatch: ic = %4d, sum = %8f, maxSum = %8f, inverseMaxSum = %8f\n", ic, sum, maxSum, inverseMaxSum ); - if( pastPeak && inversePastPeak ) - { - if( maxSum > inverseMaxSum ) - { - location = peakIndex; - } - else - { - location = inversePeakIndex; - } - break; - } - - } - //printf("PaQa_FindFirstMatch: location = %4d\n", (int)location ); - return location; + for( ic=0; icbuffer[ ic ]; + for( is=0; is maxSum) ) + { + maxSum = sum; + peakIndex = ic; + } + if( ((-sum) > inverseMaxSum) ) + { + inverseMaxSum = -sum; + inversePeakIndex = ic; + } + pastPeak = (maxSum > threshold) && (sum < 0.5*maxSum); + inversePastPeak = (inverseMaxSum > threshold) && ((-sum) < 0.5*inverseMaxSum); + //printf("PaQa_FindFirstMatch: ic = %4d, sum = %8f, maxSum = %8f, inverseMaxSum = %8f\n", ic, sum, maxSum, inverseMaxSum ); + if( pastPeak && inversePastPeak ) + { + if( maxSum > inverseMaxSum ) + { + location = peakIndex; + } + else + { + location = inversePeakIndex; + } + break; + } + + } + //printf("PaQa_FindFirstMatch: location = %4d\n", (int)location ); + return location; error: - return -1.0; + return -1.0; } /*==========================================================================================*/ // Measure the area under the curve by summing absolute value of each value. double PaQa_MeasureArea( float *buffer, int numFrames, int stride ) { - int is; - double area = 0.0; - for( is=0; isnumFrames) ); + QA_ASSERT_TRUE( "startAt+numFrames out of bounds", ((startAt+numFrames) < recording->numFrames) ); { - double recordedArea = PaQa_MeasureArea( &recording->buffer[startAt], numFrames, 1 ); - double bufferArea = PaQa_MeasureArea( buffer, numFrames, 1 ); - if( bufferArea == 0.0 ) return 100000000.0; - return recordedArea / bufferArea; + double recordedArea = PaQa_MeasureArea( &recording->buffer[startAt], numFrames, 1 ); + double bufferArea = PaQa_MeasureArea( buffer, numFrames, 1 ); + if( bufferArea == 0.0 ) return 100000000.0; + return recordedArea / bufferArea; } error: - return -1.0; + return -1.0; } /*==========================================================================================*/ double PaQa_ComputePhaseDifference( double phase1, double phase2 ) { - double delta = phase1 - phase2; - while( delta > MATH_PI ) - { - delta -= MATH_TWO_PI; - } - while( delta < -MATH_PI ) - { - delta += MATH_TWO_PI; - } - return delta; + double delta = phase1 - phase2; + while( delta > MATH_PI ) + { + delta -= MATH_TWO_PI; + } + while( delta < -MATH_PI ) + { + delta += MATH_TWO_PI; + } + return delta; } /*==========================================================================================*/ int PaQa_MeasureLatency( PaQaRecording *recording, PaQaTestTone *testTone, PaQaAnalysisResult *analysisResult ) { - double threshold; - PaQaSineGenerator generator; + double threshold; + PaQaSineGenerator generator; #define MAX_BUFFER_SIZE 2048 - float buffer[MAX_BUFFER_SIZE]; - double period = testTone->sampleRate / testTone->frequency; - int cycleSize = (int) (period + 0.5); - //printf("PaQa_AnalyseRecording: frequency = %8f, frameRate = %8f, period = %8f, cycleSize = %8d\n", - // testTone->frequency, testTone->sampleRate, period, cycleSize ); - analysisResult->latency = -1; - analysisResult->valid = (0); - - // Set up generator to find matching first cycle. - QA_ASSERT_TRUE( "cycleSize out of bounds", (cycleSize < MAX_BUFFER_SIZE) ); - PaQa_SetupSineGenerator( &generator, testTone->frequency, testTone->amplitude, testTone->sampleRate ); - PaQa_EraseBuffer( buffer, cycleSize, testTone->samplesPerFrame ); - PaQa_MixSine( &generator, buffer, cycleSize, testTone->samplesPerFrame ); - - threshold = cycleSize * 0.02; - analysisResult->latency = PaQa_FindFirstMatch( recording, buffer, cycleSize, threshold ); - QA_ASSERT_TRUE( "Could not find the start of the signal.", (analysisResult->latency >= 0) ); - analysisResult->amplitudeRatio = PaQa_CompareAmplitudes( recording, analysisResult->latency, buffer, cycleSize ); - return 0; + float buffer[MAX_BUFFER_SIZE]; + double period = testTone->sampleRate / testTone->frequency; + int cycleSize = (int) (period + 0.5); + //printf("PaQa_AnalyseRecording: frequency = %8f, frameRate = %8f, period = %8f, cycleSize = %8d\n", + // testTone->frequency, testTone->sampleRate, period, cycleSize ); + analysisResult->latency = -1; + analysisResult->valid = (0); + + // Set up generator to find matching first cycle. + QA_ASSERT_TRUE( "cycleSize out of bounds", (cycleSize < MAX_BUFFER_SIZE) ); + PaQa_SetupSineGenerator( &generator, testTone->frequency, testTone->amplitude, testTone->sampleRate ); + PaQa_EraseBuffer( buffer, cycleSize, testTone->samplesPerFrame ); + PaQa_MixSine( &generator, buffer, cycleSize, testTone->samplesPerFrame ); + + threshold = cycleSize * 0.02; + analysisResult->latency = PaQa_FindFirstMatch( recording, buffer, cycleSize, threshold ); + QA_ASSERT_TRUE( "Could not find the start of the signal.", (analysisResult->latency >= 0) ); + analysisResult->amplitudeRatio = PaQa_CompareAmplitudes( recording, analysisResult->latency, buffer, cycleSize ); + return 0; error: - return -1; + return -1; } /*==========================================================================================*/ // Apply cosine squared window. void PaQa_FadeInRecording( PaQaRecording *recording, int startFrame, int count ) { - int is; - double phase = 0.5 * MATH_PI; - // Advance a quarter wave - double phaseIncrement = 0.25 * 2.0 * MATH_PI / count; - + int is; + double phase = 0.5 * MATH_PI; + // Advance a quarter wave + double phaseIncrement = 0.25 * 2.0 * MATH_PI / count; + assert( startFrame >= 0 ); - assert( count > 0 ); - + assert( count > 0 ); + /* Zero out initial part of the recording. */ - for( is=0; isbuffer[ is ] = 0.0f; } /* Fade in where signal begins. */ for( is=0; isbuffer[ is + startFrame ]; - float y = x * w; - //printf("FADE %d : w=%f, x=%f, y=%f\n", is, w, x, y ); - recording->buffer[ is + startFrame ] = y; + double c = cos( phase ); + double w = c * c; + float x = recording->buffer[ is + startFrame ]; + float y = x * w; + //printf("FADE %d : w=%f, x=%f, y=%f\n", is, w, x, y ); + recording->buffer[ is + startFrame ] = y; phase += phaseIncrement; - } + } } @@ -539,146 +539,146 @@ void PaQa_FadeInRecording( PaQaRecording *recording, int startFrame, int count ) /** Apply notch filter and high pass filter then detect remaining energy. */ int PaQa_DetectPop( PaQaRecording *recording, PaQaTestTone *testTone, PaQaAnalysisResult *analysisResult ) -{ +{ int result = 0; - int i; + int i; double maxAmplitude; - int maxPosition; - - PaQaRecording notchOutput = { 0 }; - BiquadFilter notchFilter; - - PaQaRecording hipassOutput = { 0 }; - BiquadFilter hipassFilter; - - int frameRate = (int) recording->sampleRate; - - analysisResult->popPosition = -1; - analysisResult->popAmplitude = 0.0; - - result = PaQa_InitializeRecording( ¬chOutput, recording->numFrames, frameRate ); - QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); - - result = PaQa_InitializeRecording( &hipassOutput, recording->numFrames, frameRate ); - QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); - - // Use notch filter to remove test tone. - BiquadFilter_SetupNotch( ¬chFilter, testTone->frequency / frameRate, 0.5 ); - PaQa_FilterRecording( recording, ¬chOutput, ¬chFilter ); - //result = PaQa_SaveRecordingToWaveFile( ¬chOutput, "notch_output.wav" ); - //QA_ASSERT_EQUALS( "PaQa_SaveRecordingToWaveFile failed", 0, result ); - - // Apply fade-in window. - PaQa_FadeInRecording( ¬chOutput, (int) analysisResult->latency, 500 ); - - // Use high pass to accentuate the edges of a pop. At higher frequency! - BiquadFilter_SetupHighPass( &hipassFilter, 2.0 * testTone->frequency / frameRate, 0.5 ); - PaQa_FilterRecording( ¬chOutput, &hipassOutput, &hipassFilter ); - //result = PaQa_SaveRecordingToWaveFile( &hipassOutput, "hipass_output.wav" ); - //QA_ASSERT_EQUALS( "PaQa_SaveRecordingToWaveFile failed", 0, result ); - - // Scan remaining signal looking for peak. - maxAmplitude = 0.0; - maxPosition = -1; - for( i=(int) analysisResult->latency; i maxAmplitude ) - { - maxAmplitude = mag; - maxPosition = i; - } - } - - if( maxAmplitude > PAQA_POP_THRESHOLD ) - { - analysisResult->popPosition = maxPosition; - analysisResult->popAmplitude = maxAmplitude; - } - - PaQa_TerminateRecording( ¬chOutput ); - PaQa_TerminateRecording( &hipassOutput ); - return 0; - + int maxPosition; + + PaQaRecording notchOutput = { 0 }; + BiquadFilter notchFilter; + + PaQaRecording hipassOutput = { 0 }; + BiquadFilter hipassFilter; + + int frameRate = (int) recording->sampleRate; + + analysisResult->popPosition = -1; + analysisResult->popAmplitude = 0.0; + + result = PaQa_InitializeRecording( ¬chOutput, recording->numFrames, frameRate ); + QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); + + result = PaQa_InitializeRecording( &hipassOutput, recording->numFrames, frameRate ); + QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); + + // Use notch filter to remove test tone. + BiquadFilter_SetupNotch( ¬chFilter, testTone->frequency / frameRate, 0.5 ); + PaQa_FilterRecording( recording, ¬chOutput, ¬chFilter ); + //result = PaQa_SaveRecordingToWaveFile( ¬chOutput, "notch_output.wav" ); + //QA_ASSERT_EQUALS( "PaQa_SaveRecordingToWaveFile failed", 0, result ); + + // Apply fade-in window. + PaQa_FadeInRecording( ¬chOutput, (int) analysisResult->latency, 500 ); + + // Use high pass to accentuate the edges of a pop. At higher frequency! + BiquadFilter_SetupHighPass( &hipassFilter, 2.0 * testTone->frequency / frameRate, 0.5 ); + PaQa_FilterRecording( ¬chOutput, &hipassOutput, &hipassFilter ); + //result = PaQa_SaveRecordingToWaveFile( &hipassOutput, "hipass_output.wav" ); + //QA_ASSERT_EQUALS( "PaQa_SaveRecordingToWaveFile failed", 0, result ); + + // Scan remaining signal looking for peak. + maxAmplitude = 0.0; + maxPosition = -1; + for( i=(int) analysisResult->latency; i maxAmplitude ) + { + maxAmplitude = mag; + maxPosition = i; + } + } + + if( maxAmplitude > PAQA_POP_THRESHOLD ) + { + analysisResult->popPosition = maxPosition; + analysisResult->popAmplitude = maxAmplitude; + } + + PaQa_TerminateRecording( ¬chOutput ); + PaQa_TerminateRecording( &hipassOutput ); + return 0; + error: - PaQa_TerminateRecording( ¬chOutput ); - PaQa_TerminateRecording( &hipassOutput ); - return -1; + PaQa_TerminateRecording( ¬chOutput ); + PaQa_TerminateRecording( &hipassOutput ); + return -1; } /*==========================================================================================*/ int PaQa_DetectPhaseError( PaQaRecording *recording, PaQaTestTone *testTone, PaQaAnalysisResult *analysisResult ) -{ - int i; - double period = testTone->sampleRate / testTone->frequency; - int cycleSize = (int) (period + 0.5); - - double maxAddedFrames = 0.0; - double maxDroppedFrames = 0.0; - - double previousPhase = 0.0; - double previousFrameError = 0; - int loopCount = 0; - int skip = cycleSize; - int windowSize = cycleSize; +{ + int i; + double period = testTone->sampleRate / testTone->frequency; + int cycleSize = (int) (period + 0.5); + + double maxAddedFrames = 0.0; + double maxDroppedFrames = 0.0; + + double previousPhase = 0.0; + double previousFrameError = 0; + int loopCount = 0; + int skip = cycleSize; + int windowSize = cycleSize; // Scan recording starting with first cycle, looking for phase errors. - analysisResult->numDroppedFrames = 0.0; - analysisResult->numAddedFrames = 0.0; - analysisResult->droppedFramesPosition = -1.0; - analysisResult->addedFramesPosition = -1.0; - - for( i=analysisResult->latency; i<(recording->numFrames - windowSize); i += skip ) - { - double expectedPhase = previousPhase + (skip * MATH_TWO_PI / period); - double expectedPhaseIncrement = PaQa_ComputePhaseDifference( expectedPhase, previousPhase ); - - double phase = 666.0; - double mag = PaQa_CorrelateSine( recording, testTone->frequency, testTone->sampleRate, i, windowSize, &phase ); - if( (loopCount > 1) && (mag > 0.0) ) - { - double phaseDelta = PaQa_ComputePhaseDifference( phase, previousPhase ); - double phaseError = PaQa_ComputePhaseDifference( phaseDelta, expectedPhaseIncrement ); - // Convert phaseError to equivalent number of frames. - double frameError = period * phaseError / MATH_TWO_PI; - double consecutiveFrameError = frameError + previousFrameError; -// if( fabs(frameError) > 0.01 ) -// { -// printf("FFFFFFFFFFFFF frameError = %f, at %d\n", frameError, i ); -// } - if( consecutiveFrameError > 0.8 ) - { - double droppedFrames = consecutiveFrameError; - if (droppedFrames > (maxDroppedFrames * 1.001)) - { - analysisResult->numDroppedFrames = droppedFrames; - analysisResult->droppedFramesPosition = i + (windowSize/2); - maxDroppedFrames = droppedFrames; - } - } - else if( consecutiveFrameError < -0.8 ) - { - double addedFrames = 0 - consecutiveFrameError; - if (addedFrames > (maxAddedFrames * 1.001)) - { - analysisResult->numAddedFrames = addedFrames; - analysisResult->addedFramesPosition = i + (windowSize/2); - maxAddedFrames = addedFrames; - } - } - previousFrameError = frameError; - - - //if( i<8000 ) - //{ - // printf("%d: phase = %8f, expected = %8f, delta = %8f, frameError = %8f\n", i, phase, expectedPhaseIncrement, phaseDelta, frameError ); - //} - } - previousPhase = phase; - loopCount += 1; - } - return 0; + analysisResult->numDroppedFrames = 0.0; + analysisResult->numAddedFrames = 0.0; + analysisResult->droppedFramesPosition = -1.0; + analysisResult->addedFramesPosition = -1.0; + + for( i=analysisResult->latency; i<(recording->numFrames - windowSize); i += skip ) + { + double expectedPhase = previousPhase + (skip * MATH_TWO_PI / period); + double expectedPhaseIncrement = PaQa_ComputePhaseDifference( expectedPhase, previousPhase ); + + double phase = 666.0; + double mag = PaQa_CorrelateSine( recording, testTone->frequency, testTone->sampleRate, i, windowSize, &phase ); + if( (loopCount > 1) && (mag > 0.0) ) + { + double phaseDelta = PaQa_ComputePhaseDifference( phase, previousPhase ); + double phaseError = PaQa_ComputePhaseDifference( phaseDelta, expectedPhaseIncrement ); + // Convert phaseError to equivalent number of frames. + double frameError = period * phaseError / MATH_TWO_PI; + double consecutiveFrameError = frameError + previousFrameError; +// if( fabs(frameError) > 0.01 ) +// { +// printf("FFFFFFFFFFFFF frameError = %f, at %d\n", frameError, i ); +// } + if( consecutiveFrameError > 0.8 ) + { + double droppedFrames = consecutiveFrameError; + if (droppedFrames > (maxDroppedFrames * 1.001)) + { + analysisResult->numDroppedFrames = droppedFrames; + analysisResult->droppedFramesPosition = i + (windowSize/2); + maxDroppedFrames = droppedFrames; + } + } + else if( consecutiveFrameError < -0.8 ) + { + double addedFrames = 0 - consecutiveFrameError; + if (addedFrames > (maxAddedFrames * 1.001)) + { + analysisResult->numAddedFrames = addedFrames; + analysisResult->addedFramesPosition = i + (windowSize/2); + maxAddedFrames = addedFrames; + } + } + previousFrameError = frameError; + + + //if( i<8000 ) + //{ + // printf("%d: phase = %8f, expected = %8f, delta = %8f, frameError = %8f\n", i, phase, expectedPhaseIncrement, phaseDelta, frameError ); + //} + } + previousPhase = phase; + loopCount += 1; + } + return 0; } /*==========================================================================================*/ @@ -686,22 +686,21 @@ int PaQa_AnalyseRecording( PaQaRecording *recording, PaQaTestTone *testTone, PaQ { int result = 0; - memset( analysisResult, 0, sizeof(PaQaAnalysisResult) ); - result = PaQa_MeasureLatency( recording, testTone, analysisResult ); + memset( analysisResult, 0, sizeof(PaQaAnalysisResult) ); + result = PaQa_MeasureLatency( recording, testTone, analysisResult ); QA_ASSERT_EQUALS( "latency measurement", 0, result ); - - if( (analysisResult->latency >= 0) && (analysisResult->amplitudeRatio > 0.1) ) - { - analysisResult->valid = (1); - - result = PaQa_DetectPop( recording, testTone, analysisResult ); - QA_ASSERT_EQUALS( "detect pop", 0, result ); - - result = PaQa_DetectPhaseError( recording, testTone, analysisResult ); - QA_ASSERT_EQUALS( "detect phase error", 0, result ); - } - return 0; + + if( (analysisResult->latency >= 0) && (analysisResult->amplitudeRatio > 0.1) ) + { + analysisResult->valid = (1); + + result = PaQa_DetectPop( recording, testTone, analysisResult ); + QA_ASSERT_EQUALS( "detect pop", 0, result ); + + result = PaQa_DetectPhaseError( recording, testTone, analysisResult ); + QA_ASSERT_EQUALS( "detect phase error", 0, result ); + } + return 0; error: - return -1; + return -1; } - diff --git a/3rdparty/portaudio/qa/loopback/src/audio_analyzer.h b/3rdparty/portaudio/qa/loopback/src/audio_analyzer.h index 2a867983ba2..8d9f1ee4f60 100644 --- a/3rdparty/portaudio/qa/loopback/src/audio_analyzer.h +++ b/3rdparty/portaudio/qa/loopback/src/audio_analyzer.h @@ -26,13 +26,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -46,44 +46,44 @@ typedef struct PaQaSineGenerator_s { - double phase; - double phaseIncrement; - double frequency; - double amplitude; + double phase; + double phaseIncrement; + double frequency; + double amplitude; } PaQaSineGenerator; -/** Container for a monophonic audio sample in memory. */ +/** Container for a monophonic audio sample in memory. */ typedef struct PaQaRecording_s { - /** Maximum number of frames that can fit in the allocated buffer. */ - int maxFrames; - float *buffer; - /** Actual number of valid frames in the buffer. */ - int numFrames; - int sampleRate; + /** Maximum number of frames that can fit in the allocated buffer. */ + int maxFrames; + float *buffer; + /** Actual number of valid frames in the buffer. */ + int numFrames; + int sampleRate; } PaQaRecording; typedef struct PaQaTestTone_s { - int samplesPerFrame; - int startDelay; - double sampleRate; - double frequency; - double amplitude; + int samplesPerFrame; + int startDelay; + double sampleRate; + double frequency; + double amplitude; } PaQaTestTone; typedef struct PaQaAnalysisResult_s { - int valid; - /** Latency in samples from output to input. */ - double latency; - double amplitudeRatio; - double popAmplitude; - double popPosition; - double numDroppedFrames; - double droppedFramesPosition; - double numAddedFrames; - double addedFramesPosition; + int valid; + /** Latency in samples from output to input. */ + double latency; + double amplitudeRatio; + double popAmplitude; + double popPosition; + double numDroppedFrames; + double droppedFramesPosition; + double numAddedFrames; + double addedFramesPosition; } PaQaAnalysisResult; @@ -101,7 +101,7 @@ void PaQa_EraseBuffer( float *buffer, int numFrames, int samplesPerFrame ); void PaQa_MixSine( PaQaSineGenerator *generator, float *buffer, int numSamples, int stride ); void PaQa_WriteSine( float *buffer, int numSamples, int stride, - double frequency, double amplitude ); + double frequency, double amplitude ); /** * Generate a signal with a sharp edge in the middle that can be recognized despite some phase shift. @@ -130,15 +130,15 @@ void PaQa_SetupSineGenerator( PaQaSineGenerator *generator, double frequency, do /*================= Recordings ===================================*/ /*================================================================*/ /** - * Allocate memory for containg a mono audio signal. Set up recording for writing. + * Allocate memory for containing a mono audio signal. Set up recording for writing. */ int PaQa_InitializeRecording( PaQaRecording *recording, int maxSamples, int sampleRate ); - + /** * Free memory allocated by PaQa_InitializeRecording. */ void PaQa_TerminateRecording( PaQaRecording *recording ); - + /** * Apply a biquad filter to the audio from the input recording and write it to the output recording. */ @@ -146,29 +146,29 @@ void PaQa_FilterRecording( PaQaRecording *input, PaQaRecording *output, BiquadFi int PaQa_SaveRecordingToWaveFile( PaQaRecording *recording, const char *filename ); - + /** * @param stride is the spacing of samples to skip in the input buffer. To use every samples pass 1. To use every other sample pass 2. */ int PaQa_WriteRecording( PaQaRecording *recording, float *buffer, int numSamples, int stride ); - + /** Write zeros into a recording. */ int PaQa_WriteSilence( PaQaRecording *recording, int numSamples ); - + int PaQa_RecordFreeze( PaQaRecording *recording, int numSamples ); double PaQa_CorrelateSine( PaQaRecording *recording, double frequency, double frameRate, - int startFrame, int numSamples, double *phasePtr ); + int startFrame, int numSamples, double *phasePtr ); double PaQa_FindFirstMatch( PaQaRecording *recording, float *buffer, int numSamples, double tolerance ); -/** +/** * Estimate the original amplitude of a clipped sine wave by measuring * its average slope at the zero crossings. */ double PaQa_MeasureSineAmplitudeBySlope( PaQaRecording *recording, - double frequency, double frameRate, - int startFrame, int numFrames ); + double frequency, double frameRate, + int startFrame, int numFrames ); double PaQa_MeasureRootMeanSquare( float *buffer, int numFrames ); diff --git a/3rdparty/portaudio/qa/loopback/src/biquad_filter.c b/3rdparty/portaudio/qa/loopback/src/biquad_filter.c index 1bc4a232ab6..1715fa3c65a 100755 --- a/3rdparty/portaudio/qa/loopback/src/biquad_filter.c +++ b/3rdparty/portaudio/qa/loopback/src/biquad_filter.c @@ -4,9 +4,10 @@ #include "biquad_filter.h" /** - * Unit_BiquadFilter implements a second order IIR filter. - Here is the equation that we use for this filter: - y(n) = a0*x(n) + a1*x(n-1) + a2*x(n-2) - b1*y(n-1) - b2*y(n-2) + * Unit_BiquadFilter implements a second order IIR filter. + * + * Here is the equation that we use for this filter: + * y(n) = a0*x(n) + a1*x(n-1) + a2*x(n-2) - b1*y(n-1) - b2*y(n-2) * * @author (C) 2002 Phil Burk, SoftSynth.com, All Rights Reserved */ @@ -17,17 +18,17 @@ */ static void BiquadFilter_CalculateCommon( BiquadFilter *filter, double ratio, double Q ) { - double omega; - - memset( filter, 0, sizeof(BiquadFilter) ); + double omega; + + memset( filter, 0, sizeof(BiquadFilter) ); /* Don't let frequency get too close to Nyquist or filter will blow up. */ - if( ratio >= 0.499 ) ratio = 0.499; - omega = 2.0 * (double)FILTER_PI * ratio; + if( ratio >= 0.499 ) ratio = 0.499; + omega = 2.0 * (double)FILTER_PI * ratio; - filter->cos_omega = (double) cos( omega ); - filter->sin_omega = (double) sin( omega ); - filter->alpha = filter->sin_omega / (2.0 * Q); + filter->cos_omega = (double) cos( omega ); + filter->sin_omega = (double) sin( omega ); + filter->alpha = filter->sin_omega / (2.0 * Q); } /********************************************************************************* @@ -35,21 +36,21 @@ static void BiquadFilter_CalculateCommon( BiquadFilter *filter, double ratio, do */ void BiquadFilter_SetupHighPass( BiquadFilter *filter, double ratio, double Q ) { - double scalar, opc; - - if( ratio < BIQUAD_MIN_RATIO ) ratio = BIQUAD_MIN_RATIO; - if( Q < BIQUAD_MIN_Q ) Q = BIQUAD_MIN_Q; - - BiquadFilter_CalculateCommon( filter, ratio, Q ); - - scalar = 1.0 / (1.0 + filter->alpha); - opc = (1.0 + filter->cos_omega); - - filter->a0 = opc * 0.5 * scalar; - filter->a1 = - opc * scalar; + double scalar, opc; + + if( ratio < BIQUAD_MIN_RATIO ) ratio = BIQUAD_MIN_RATIO; + if( Q < BIQUAD_MIN_Q ) Q = BIQUAD_MIN_Q; + + BiquadFilter_CalculateCommon( filter, ratio, Q ); + + scalar = 1.0 / (1.0 + filter->alpha); + opc = (1.0 + filter->cos_omega); + + filter->a0 = opc * 0.5 * scalar; + filter->a1 = - opc * scalar; filter->a2 = filter->a0; - filter->b1 = -2.0 * filter->cos_omega * scalar; - filter->b2 = (1.0 - filter->alpha) * scalar; + filter->b1 = -2.0 * filter->cos_omega * scalar; + filter->b2 = (1.0 - filter->alpha) * scalar; } @@ -58,21 +59,21 @@ void BiquadFilter_SetupHighPass( BiquadFilter *filter, double ratio, double Q ) */ void BiquadFilter_SetupNotch( BiquadFilter *filter, double ratio, double Q ) { - double scalar, opc; - - if( ratio < BIQUAD_MIN_RATIO ) ratio = BIQUAD_MIN_RATIO; - if( Q < BIQUAD_MIN_Q ) Q = BIQUAD_MIN_Q; - - BiquadFilter_CalculateCommon( filter, ratio, Q ); - - scalar = 1.0 / (1.0 + filter->alpha); - opc = (1.0 + filter->cos_omega); - - filter->a0 = scalar; - filter->a1 = -2.0 * filter->cos_omega * scalar; + double scalar, opc; + + if( ratio < BIQUAD_MIN_RATIO ) ratio = BIQUAD_MIN_RATIO; + if( Q < BIQUAD_MIN_Q ) Q = BIQUAD_MIN_Q; + + BiquadFilter_CalculateCommon( filter, ratio, Q ); + + scalar = 1.0 / (1.0 + filter->alpha); + opc = (1.0 + filter->cos_omega); + + filter->a0 = scalar; + filter->a1 = -2.0 * filter->cos_omega * scalar; filter->a2 = filter->a0; - filter->b1 = filter->a1; - filter->b2 = (1.0 - filter->alpha) * scalar; + filter->b1 = filter->a1; + filter->b2 = (1.0 - filter->alpha) * scalar; } /***************************************************************** @@ -80,43 +81,43 @@ void BiquadFilter_SetupNotch( BiquadFilter *filter, double ratio, double Q ) */ void BiquadFilter_Filter( BiquadFilter *filter, float *inputs, float *outputs, int numSamples ) { - int i; + int i; double xn, yn; - // Pull values from structure to speed up the calculation. - double a0 = filter->a0; - double a1 = filter->a1; - double a2 = filter->a2; - double b1 = filter->b1; - double b2 = filter->b2; - double xn1 = filter->xn1; - double xn2 = filter->xn2; - double yn1 = filter->yn1; - double yn2 = filter->yn2; - - for( i=0; ia0; + double a1 = filter->a1; + double a2 = filter->a2; + double b1 = filter->b1; + double b2 = filter->b2; + double xn1 = filter->xn1; + double xn2 = filter->xn2; + double yn1 = filter->yn1; + double yn2 = filter->yn2; + + for( i=0; ixn1 = xn1; - filter->xn2 = xn2; - filter->yn1 = yn1; - filter->yn2 = yn2; + + if( (i & 7) == 0 ) + { + // Apply a small bipolar impulse to filter to prevent arithmetic underflow. + // Underflows can cause the FPU to interrupt the CPU. + yn1 += (double) 1.0E-26; + yn2 -= (double) 1.0E-26; + } + } + + filter->xn1 = xn1; + filter->xn2 = xn2; + filter->yn1 = yn1; + filter->yn2 = yn2; } diff --git a/3rdparty/portaudio/qa/loopback/src/biquad_filter.h b/3rdparty/portaudio/qa/loopback/src/biquad_filter.h index cbac688b6fd..0895abae73e 100755 --- a/3rdparty/portaudio/qa/loopback/src/biquad_filter.h +++ b/3rdparty/portaudio/qa/loopback/src/biquad_filter.h @@ -3,7 +3,7 @@ /** - * Unit_BiquadFilter implements a second order IIR filter. + * Unit_BiquadFilter implements a second order IIR filter. * * @author (C) 2002 Phil Burk, SoftSynth.com, All Rights Reserved */ @@ -14,20 +14,20 @@ typedef struct BiquadFilter_s { double xn1; // storage for delayed signals - double xn2; - double yn1; - double yn2; + double xn2; + double yn1; + double yn2; - double a0; // coefficients - double a1; - double a2; + double a0; // coefficients + double a1; + double a2; - double b1; - double b2; + double b1; + double b2; - double cos_omega; - double sin_omega; - double alpha; + double cos_omega; + double sin_omega; + double alpha; } BiquadFilter; void BiquadFilter_SetupHighPass( BiquadFilter *filter, double ratio, double Q ); diff --git a/3rdparty/portaudio/qa/loopback/src/paqa.c b/3rdparty/portaudio/qa/loopback/src/paqa.c index cb7100d7807..a3ed4acfb55 100644 --- a/3rdparty/portaudio/qa/loopback/src/paqa.c +++ b/3rdparty/portaudio/qa/loopback/src/paqa.c @@ -26,13 +26,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -69,76 +69,76 @@ int g_testsFailed = 0; const char * s_FlagOnNames[] = { - "Two Streams (Half Duplex)", - "Blocking Read/Write" + "Two Streams (Half Duplex)", + "Blocking Read/Write" }; const char * s_FlagOffNames[] = { - "One Stream (Full Duplex)", - "Callback" + "One Stream (Full Duplex)", + "Callback" }; /** Parameters that describe a single test run. */ typedef struct TestParameters_s { - PaStreamParameters inputParameters; - PaStreamParameters outputParameters; - double sampleRate; - int samplesPerFrame; - int framesPerBuffer; - int maxFrames; - double baseFrequency; - double amplitude; + PaStreamParameters inputParameters; + PaStreamParameters outputParameters; + double sampleRate; + int samplesPerFrame; + int framesPerBuffer; + int maxFrames; + double baseFrequency; + double amplitude; PaStreamFlags streamFlags; // paClipOff, etc - int flags; // PAQA_FLAG_TWO_STREAMS, PAQA_FLAG_USE_BLOCKING_IO + int flags; // PAQA_FLAG_TWO_STREAMS, PAQA_FLAG_USE_BLOCKING_IO } TestParameters; typedef struct LoopbackContext_s { - // Generate a unique signal on each channel. - PaQaSineGenerator generators[MAX_NUM_GENERATORS]; - // Record each channel individually. - PaQaRecording recordings[MAX_NUM_RECORDINGS]; - - // Reported by the stream after it's opened - PaTime streamInfoInputLatency; - PaTime streamInfoOutputLatency; - - // Measured at runtime. - volatile int callbackCount; // incremented for each callback - volatile int inputBufferCount; // incremented if input buffer not NULL - int inputUnderflowCount; - int inputOverflowCount; - - volatile int outputBufferCount; // incremented if output buffer not NULL - int outputOverflowCount; - int outputUnderflowCount; - + // Generate a unique signal on each channel. + PaQaSineGenerator generators[MAX_NUM_GENERATORS]; + // Record each channel individually. + PaQaRecording recordings[MAX_NUM_RECORDINGS]; + + // Reported by the stream after it's opened + PaTime streamInfoInputLatency; + PaTime streamInfoOutputLatency; + + // Measured at runtime. + volatile int callbackCount; // incremented for each callback + volatile int inputBufferCount; // incremented if input buffer not NULL + int inputUnderflowCount; + int inputOverflowCount; + + volatile int outputBufferCount; // incremented if output buffer not NULL + int outputOverflowCount; + int outputUnderflowCount; + // Measure whether input or output is lagging behind. volatile int minInputOutputDelta; volatile int maxInputOutputDelta; - - int minFramesPerBuffer; - int maxFramesPerBuffer; - int primingCount; - TestParameters *test; - volatile int done; + + int minFramesPerBuffer; + int maxFramesPerBuffer; + int primingCount; + TestParameters *test; + volatile int done; } LoopbackContext; typedef struct UserOptions_s { - int sampleRate; - int framesPerBuffer; - int inputLatency; - int outputLatency; - int saveBadWaves; - int verbose; - int waveFileCount; - const char *waveFilePath; - PaDeviceIndex inputDevice; - PaDeviceIndex outputDevice; + int sampleRate; + int framesPerBuffer; + int inputLatency; + int outputLatency; + int saveBadWaves; + int verbose; + int waveFileCount; + const char *waveFilePath; + PaDeviceIndex inputDevice; + PaDeviceIndex outputDevice; } UserOptions; #define BIG_BUFFER_SIZE (sizeof(float) * 2 * 2 * 1024) @@ -150,105 +150,105 @@ static unsigned char g_ConversionBuffer[CONVERSION_BUFFER_SIZE]; /*******************************************************************/ static int RecordAndPlaySinesCallback( const void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, - void *userData ) + unsigned long framesPerBuffer, + const PaStreamCallbackTimeInfo* timeInfo, + PaStreamCallbackFlags statusFlags, + void *userData ) { - int i; - LoopbackContext *loopbackContext = (LoopbackContext *) userData; - - - loopbackContext->callbackCount += 1; - if( statusFlags & paInputUnderflow ) loopbackContext->inputUnderflowCount += 1; - if( statusFlags & paInputOverflow ) loopbackContext->inputOverflowCount += 1; - if( statusFlags & paOutputUnderflow ) loopbackContext->outputUnderflowCount += 1; - if( statusFlags & paOutputOverflow ) loopbackContext->outputOverflowCount += 1; - if( statusFlags & paPrimingOutput ) loopbackContext->primingCount += 1; - if( framesPerBuffer > loopbackContext->maxFramesPerBuffer ) - { - loopbackContext->maxFramesPerBuffer = framesPerBuffer; - } - if( framesPerBuffer < loopbackContext->minFramesPerBuffer ) - { - loopbackContext->minFramesPerBuffer = framesPerBuffer; - } - + int i; + LoopbackContext *loopbackContext = (LoopbackContext *) userData; + + + loopbackContext->callbackCount += 1; + if( statusFlags & paInputUnderflow ) loopbackContext->inputUnderflowCount += 1; + if( statusFlags & paInputOverflow ) loopbackContext->inputOverflowCount += 1; + if( statusFlags & paOutputUnderflow ) loopbackContext->outputUnderflowCount += 1; + if( statusFlags & paOutputOverflow ) loopbackContext->outputOverflowCount += 1; + if( statusFlags & paPrimingOutput ) loopbackContext->primingCount += 1; + if( framesPerBuffer > loopbackContext->maxFramesPerBuffer ) + { + loopbackContext->maxFramesPerBuffer = framesPerBuffer; + } + if( framesPerBuffer < loopbackContext->minFramesPerBuffer ) + { + loopbackContext->minFramesPerBuffer = framesPerBuffer; + } + /* This may get called with NULL inputBuffer during initial setup. - * We may also use the same callback with output only streams. - */ - if( inputBuffer != NULL) - { - int channelsPerFrame = loopbackContext->test->inputParameters.channelCount; - float *in = (float *)inputBuffer; - PaSampleFormat inFormat = loopbackContext->test->inputParameters.sampleFormat; - - loopbackContext->inputBufferCount += 1; - - if( inFormat != paFloat32 ) - { - int samplesToConvert = framesPerBuffer * channelsPerFrame; - in = (float *) g_ConversionBuffer; - if( samplesToConvert > MAX_CONVERSION_SAMPLES ) - { - // Hack to prevent buffer overflow. - // @todo Loop with small buffer instead of failing. - printf("Format conversion buffer too small!\n"); - return paComplete; - } - PaQa_ConvertToFloat( inputBuffer, samplesToConvert, inFormat, (float *) g_ConversionBuffer ); - } - - // Read each channel from the buffer. - for( i=0; idone |= PaQa_WriteRecording( &loopbackContext->recordings[i], - in + i, - framesPerBuffer, - channelsPerFrame ); - } - } - - if( outputBuffer != NULL ) - { - int channelsPerFrame = loopbackContext->test->outputParameters.channelCount; - float *out = (float *)outputBuffer; - PaSampleFormat outFormat = loopbackContext->test->outputParameters.sampleFormat; - - loopbackContext->outputBufferCount += 1; - - if( outFormat != paFloat32 ) - { - // If we need to convert then mix to the g_ConversionBuffer and then convert into the PA outputBuffer. - out = (float *) g_ConversionBuffer; - } - - PaQa_EraseBuffer( out, framesPerBuffer, channelsPerFrame ); - for( i=0; igenerators[i], - out + i, - framesPerBuffer, - channelsPerFrame ); - } - - if( outFormat != paFloat32 ) - { - int samplesToConvert = framesPerBuffer * channelsPerFrame; - if( samplesToConvert > MAX_CONVERSION_SAMPLES ) - { - printf("Format conversion buffer too small!\n"); - return paComplete; - } - PaQa_ConvertFromFloat( out, framesPerBuffer * channelsPerFrame, outFormat, outputBuffer ); - } - - } - + * We may also use the same callback with output only streams. + */ + if( inputBuffer != NULL) + { + int channelsPerFrame = loopbackContext->test->inputParameters.channelCount; + float *in = (float *)inputBuffer; + PaSampleFormat inFormat = loopbackContext->test->inputParameters.sampleFormat; + + loopbackContext->inputBufferCount += 1; + + if( inFormat != paFloat32 ) + { + int samplesToConvert = framesPerBuffer * channelsPerFrame; + in = (float *) g_ConversionBuffer; + if( samplesToConvert > MAX_CONVERSION_SAMPLES ) + { + // Hack to prevent buffer overflow. + // @todo Loop with small buffer instead of failing. + printf("Format conversion buffer too small!\n"); + return paComplete; + } + PaQa_ConvertToFloat( inputBuffer, samplesToConvert, inFormat, (float *) g_ConversionBuffer ); + } + + // Read each channel from the buffer. + for( i=0; idone |= PaQa_WriteRecording( &loopbackContext->recordings[i], + in + i, + framesPerBuffer, + channelsPerFrame ); + } + } + + if( outputBuffer != NULL ) + { + int channelsPerFrame = loopbackContext->test->outputParameters.channelCount; + float *out = (float *)outputBuffer; + PaSampleFormat outFormat = loopbackContext->test->outputParameters.sampleFormat; + + loopbackContext->outputBufferCount += 1; + + if( outFormat != paFloat32 ) + { + // If we need to convert then mix to the g_ConversionBuffer and then convert into the PA outputBuffer. + out = (float *) g_ConversionBuffer; + } + + PaQa_EraseBuffer( out, framesPerBuffer, channelsPerFrame ); + for( i=0; igenerators[i], + out + i, + framesPerBuffer, + channelsPerFrame ); + } + + if( outFormat != paFloat32 ) + { + int samplesToConvert = framesPerBuffer * channelsPerFrame; + if( samplesToConvert > MAX_CONVERSION_SAMPLES ) + { + printf("Format conversion buffer too small!\n"); + return paComplete; + } + PaQa_ConvertFromFloat( out, framesPerBuffer * channelsPerFrame, outFormat, outputBuffer ); + } + + } + // Measure whether the input or output are lagging behind. // Don't measure lag at end. if( !loopbackContext->done ) - { + { int inputOutputDelta = loopbackContext->inputBufferCount - loopbackContext->outputBufferCount; if( loopbackContext->maxInputOutputDelta < inputOutputDelta ) { @@ -259,21 +259,21 @@ static int RecordAndPlaySinesCallback( const void *inputBuffer, void *outputBuff loopbackContext->minInputOutputDelta = inputOutputDelta; } } - - return loopbackContext->done ? paComplete : paContinue; + + return loopbackContext->done ? paComplete : paContinue; } static void CopyStreamInfoToLoopbackContext( LoopbackContext *loopbackContext, PaStream *inputStream, PaStream *outputStream ) { - const PaStreamInfo *inputStreamInfo = Pa_GetStreamInfo( inputStream ); - const PaStreamInfo *outputStreamInfo = Pa_GetStreamInfo( outputStream ); + const PaStreamInfo *inputStreamInfo = Pa_GetStreamInfo( inputStream ); + const PaStreamInfo *outputStreamInfo = Pa_GetStreamInfo( outputStream ); - loopbackContext->streamInfoInputLatency = inputStreamInfo ? inputStreamInfo->inputLatency : -1; - loopbackContext->streamInfoOutputLatency = outputStreamInfo ? outputStreamInfo->outputLatency : -1; + loopbackContext->streamInfoInputLatency = inputStreamInfo ? inputStreamInfo->inputLatency : -1; + loopbackContext->streamInfoOutputLatency = outputStreamInfo ? outputStreamInfo->outputLatency : -1; } /*******************************************************************/ -/** +/** * Open a full duplex audio stream. * Generate sine waves on the output channels and record the input channels. * Then close the stream. @@ -281,47 +281,47 @@ static void CopyStreamInfoToLoopbackContext( LoopbackContext *loopbackContext, P */ int PaQa_RunLoopbackFullDuplex( LoopbackContext *loopbackContext ) { - PaStream *stream = NULL; - PaError err = 0; - TestParameters *test = loopbackContext->test; - loopbackContext->done = 0; - // Use one full duplex stream. - err = Pa_OpenStream( - &stream, - &test->inputParameters, - &test->outputParameters, - test->sampleRate, - test->framesPerBuffer, - paClipOff, /* we won't output out of range samples so don't bother clipping them */ - RecordAndPlaySinesCallback, - loopbackContext ); - if( err != paNoError ) goto error; - - CopyStreamInfoToLoopbackContext( loopbackContext, stream, stream ); - - err = Pa_StartStream( stream ); - if( err != paNoError ) goto error; - - // Wait for stream to finish. - while( loopbackContext->done == 0 ) - { - Pa_Sleep(PAQA_WAIT_STREAM_MSEC); - } - - err = Pa_StopStream( stream ); - if( err != paNoError ) goto error; - - err = Pa_CloseStream( stream ); - if( err != paNoError ) goto error; - - return 0; - + PaStream *stream = NULL; + PaError err = 0; + TestParameters *test = loopbackContext->test; + loopbackContext->done = 0; + // Use one full duplex stream. + err = Pa_OpenStream( + &stream, + &test->inputParameters, + &test->outputParameters, + test->sampleRate, + test->framesPerBuffer, + paClipOff, /* we won't output out of range samples so don't bother clipping them */ + RecordAndPlaySinesCallback, + loopbackContext ); + if( err != paNoError ) goto error; + + CopyStreamInfoToLoopbackContext( loopbackContext, stream, stream ); + + err = Pa_StartStream( stream ); + if( err != paNoError ) goto error; + + // Wait for stream to finish. + while( loopbackContext->done == 0 ) + { + Pa_Sleep(PAQA_WAIT_STREAM_MSEC); + } + + err = Pa_StopStream( stream ); + if( err != paNoError ) goto error; + + err = Pa_CloseStream( stream ); + if( err != paNoError ) goto error; + + return 0; + error: - return err; + return err; } /*******************************************************************/ -/** +/** * Open two audio streams, one for input and one for output. * Generate sine waves on the output channels and record the input channels. * Then close the stream. @@ -330,25 +330,25 @@ error: int PaQa_WaitForStream( LoopbackContext *loopbackContext ) { - int timeoutMSec = 1000 * PAQA_TEST_DURATION * 2; - - // Wait for stream to finish or timeout. - while( (loopbackContext->done == 0) && (timeoutMSec > 0) ) - { - Pa_Sleep(PAQA_WAIT_STREAM_MSEC); - timeoutMSec -= PAQA_WAIT_STREAM_MSEC; - } - - if( loopbackContext->done == 0 ) - { - printf("ERROR - stream completion timed out!"); - return paTimedOut; - } - return 0; + int timeoutMSec = 1000 * PAQA_TEST_DURATION * 2; + + // Wait for stream to finish or timeout. + while( (loopbackContext->done == 0) && (timeoutMSec > 0) ) + { + Pa_Sleep(PAQA_WAIT_STREAM_MSEC); + timeoutMSec -= PAQA_WAIT_STREAM_MSEC; + } + + if( loopbackContext->done == 0 ) + { + printf("ERROR - stream completion timed out!"); + return paTimedOut; + } + return 0; } /*******************************************************************/ -/** +/** * Open two audio streams, one for input and one for output. * Generate sine waves on the output channels and record the input channels. * Then close the stream. @@ -356,67 +356,67 @@ int PaQa_WaitForStream( LoopbackContext *loopbackContext ) */ int PaQa_RunLoopbackHalfDuplex( LoopbackContext *loopbackContext ) { - PaStream *inStream = NULL; - PaStream *outStream = NULL; - PaError err = 0; - int timedOut = 0; - TestParameters *test = loopbackContext->test; - loopbackContext->done = 0; - - // Use two half duplex streams. - err = Pa_OpenStream( - &inStream, - &test->inputParameters, - NULL, - test->sampleRate, - test->framesPerBuffer, - test->streamFlags, - RecordAndPlaySinesCallback, - loopbackContext ); - if( err != paNoError ) goto error; - err = Pa_OpenStream( - &outStream, - NULL, - &test->outputParameters, - test->sampleRate, - test->framesPerBuffer, - test->streamFlags, - RecordAndPlaySinesCallback, - loopbackContext ); - if( err != paNoError ) goto error; - - CopyStreamInfoToLoopbackContext( loopbackContext, inStream, outStream ); - - err = Pa_StartStream( inStream ); - if( err != paNoError ) goto error; - - // Start output later so we catch the beginning of the waveform. - err = Pa_StartStream( outStream ); - if( err != paNoError ) goto error; - - timedOut = PaQa_WaitForStream( loopbackContext ); - - err = Pa_StopStream( inStream ); - if( err != paNoError ) goto error; - - err = Pa_StopStream( outStream ); - if( err != paNoError ) goto error; - - err = Pa_CloseStream( inStream ); - if( err != paNoError ) goto error; - - err = Pa_CloseStream( outStream ); - if( err != paNoError ) goto error; - - return timedOut; - + PaStream *inStream = NULL; + PaStream *outStream = NULL; + PaError err = 0; + int timedOut = 0; + TestParameters *test = loopbackContext->test; + loopbackContext->done = 0; + + // Use two half duplex streams. + err = Pa_OpenStream( + &inStream, + &test->inputParameters, + NULL, + test->sampleRate, + test->framesPerBuffer, + test->streamFlags, + RecordAndPlaySinesCallback, + loopbackContext ); + if( err != paNoError ) goto error; + err = Pa_OpenStream( + &outStream, + NULL, + &test->outputParameters, + test->sampleRate, + test->framesPerBuffer, + test->streamFlags, + RecordAndPlaySinesCallback, + loopbackContext ); + if( err != paNoError ) goto error; + + CopyStreamInfoToLoopbackContext( loopbackContext, inStream, outStream ); + + err = Pa_StartStream( inStream ); + if( err != paNoError ) goto error; + + // Start output later so we catch the beginning of the waveform. + err = Pa_StartStream( outStream ); + if( err != paNoError ) goto error; + + timedOut = PaQa_WaitForStream( loopbackContext ); + + err = Pa_StopStream( inStream ); + if( err != paNoError ) goto error; + + err = Pa_StopStream( outStream ); + if( err != paNoError ) goto error; + + err = Pa_CloseStream( inStream ); + if( err != paNoError ) goto error; + + err = Pa_CloseStream( outStream ); + if( err != paNoError ) goto error; + + return timedOut; + error: - return err; + return err; } /*******************************************************************/ -/** +/** * Open one audio streams, just for input. * Record background level. * Then close the stream. @@ -424,120 +424,120 @@ error: */ int PaQa_RunInputOnly( LoopbackContext *loopbackContext ) { - PaStream *inStream = NULL; - PaError err = 0; - int timedOut = 0; - TestParameters *test = loopbackContext->test; - loopbackContext->done = 0; - - // Just open an input stream. - err = Pa_OpenStream( - &inStream, - &test->inputParameters, - NULL, - test->sampleRate, - test->framesPerBuffer, - paClipOff, /* We won't output out of range samples so don't bother clipping them. */ - RecordAndPlaySinesCallback, - loopbackContext ); - if( err != paNoError ) goto error; - - err = Pa_StartStream( inStream ); - if( err != paNoError ) goto error; - - timedOut = PaQa_WaitForStream( loopbackContext ); - - err = Pa_StopStream( inStream ); - if( err != paNoError ) goto error; - - err = Pa_CloseStream( inStream ); - if( err != paNoError ) goto error; - - return timedOut; - + PaStream *inStream = NULL; + PaError err = 0; + int timedOut = 0; + TestParameters *test = loopbackContext->test; + loopbackContext->done = 0; + + // Just open an input stream. + err = Pa_OpenStream( + &inStream, + &test->inputParameters, + NULL, + test->sampleRate, + test->framesPerBuffer, + paClipOff, /* We won't output out of range samples so don't bother clipping them. */ + RecordAndPlaySinesCallback, + loopbackContext ); + if( err != paNoError ) goto error; + + err = Pa_StartStream( inStream ); + if( err != paNoError ) goto error; + + timedOut = PaQa_WaitForStream( loopbackContext ); + + err = Pa_StopStream( inStream ); + if( err != paNoError ) goto error; + + err = Pa_CloseStream( inStream ); + if( err != paNoError ) goto error; + + return timedOut; + error: - return err; + return err; } /*******************************************************************/ static int RecordAndPlayBlockingIO( PaStream *inStream, - PaStream *outStream, - LoopbackContext *loopbackContext - ) -{ - int i; - float *in = (float *)g_ReadWriteBuffer; - float *out = (float *)g_ReadWriteBuffer; - PaError err; - int done = 0; - long available; - const long maxPerBuffer = 64; - TestParameters *test = loopbackContext->test; - long framesPerBuffer = test->framesPerBuffer; - if( framesPerBuffer <= 0 ) - { - framesPerBuffer = maxPerBuffer; // bigger values might run past end of recording - } - - // Read in audio. - err = Pa_ReadStream( inStream, in, framesPerBuffer ); - // Ignore an overflow on the first read. - //if( !((loopbackContext->callbackCount == 0) && (err == paInputOverflowed)) ) - if( err != paInputOverflowed ) - { - QA_ASSERT_EQUALS( "Pa_ReadStream failed", paNoError, err ); - } - else - { - loopbackContext->inputOverflowCount += 1; - } - - - // Save in a recording. - for( i=0; itest->inputParameters.channelCount; i++ ) - { - done |= PaQa_WriteRecording( &loopbackContext->recordings[i], - in + i, - framesPerBuffer, - loopbackContext->test->inputParameters.channelCount ); - } - - // Synthesize audio. - available = Pa_GetStreamWriteAvailable( outStream ); - if( available > (2*framesPerBuffer) ) available = (2*framesPerBuffer); - PaQa_EraseBuffer( out, available, loopbackContext->test->outputParameters.channelCount ); - for( i=0; itest->outputParameters.channelCount; i++ ) - { - PaQa_MixSine( &loopbackContext->generators[i], - out + i, - available, - loopbackContext->test->outputParameters.channelCount ); - } - - // Write out audio. - err = Pa_WriteStream( outStream, out, available ); - // Ignore an underflow on the first write. - //if( !((loopbackContext->callbackCount == 0) && (err == paOutputUnderflowed)) ) - if( err != paOutputUnderflowed ) - { - QA_ASSERT_EQUALS( "Pa_WriteStream failed", paNoError, err ); - } - else - { - loopbackContext->outputUnderflowCount += 1; - } - - - loopbackContext->callbackCount += 1; - - return done; + PaStream *outStream, + LoopbackContext *loopbackContext + ) +{ + int i; + float *in = (float *)g_ReadWriteBuffer; + float *out = (float *)g_ReadWriteBuffer; + PaError err; + int done = 0; + long available; + const long maxPerBuffer = 64; + TestParameters *test = loopbackContext->test; + long framesPerBuffer = test->framesPerBuffer; + if( framesPerBuffer <= 0 ) + { + framesPerBuffer = maxPerBuffer; // bigger values might run past end of recording + } + + // Read in audio. + err = Pa_ReadStream( inStream, in, framesPerBuffer ); + // Ignore an overflow on the first read. + //if( !((loopbackContext->callbackCount == 0) && (err == paInputOverflowed)) ) + if( err != paInputOverflowed ) + { + QA_ASSERT_EQUALS( "Pa_ReadStream failed", paNoError, err ); + } + else + { + loopbackContext->inputOverflowCount += 1; + } + + + // Save in a recording. + for( i=0; itest->inputParameters.channelCount; i++ ) + { + done |= PaQa_WriteRecording( &loopbackContext->recordings[i], + in + i, + framesPerBuffer, + loopbackContext->test->inputParameters.channelCount ); + } + + // Synthesize audio. + available = Pa_GetStreamWriteAvailable( outStream ); + if( available > (2*framesPerBuffer) ) available = (2*framesPerBuffer); + PaQa_EraseBuffer( out, available, loopbackContext->test->outputParameters.channelCount ); + for( i=0; itest->outputParameters.channelCount; i++ ) + { + PaQa_MixSine( &loopbackContext->generators[i], + out + i, + available, + loopbackContext->test->outputParameters.channelCount ); + } + + // Write out audio. + err = Pa_WriteStream( outStream, out, available ); + // Ignore an underflow on the first write. + //if( !((loopbackContext->callbackCount == 0) && (err == paOutputUnderflowed)) ) + if( err != paOutputUnderflowed ) + { + QA_ASSERT_EQUALS( "Pa_WriteStream failed", paNoError, err ); + } + else + { + loopbackContext->outputUnderflowCount += 1; + } + + + loopbackContext->callbackCount += 1; + + return done; error: - return err; + return err; } /*******************************************************************/ -/** +/** * Open two audio streams with non-blocking IO. * Generate sine waves on the output channels and record the input channels. * Then close the stream. @@ -545,73 +545,73 @@ error: */ int PaQa_RunLoopbackHalfDuplexBlockingIO( LoopbackContext *loopbackContext ) { - PaStream *inStream = NULL; - PaStream *outStream = NULL; - PaError err = 0; - TestParameters *test = loopbackContext->test; - - // Use two half duplex streams. - err = Pa_OpenStream( - &inStream, - &test->inputParameters, - NULL, - test->sampleRate, - test->framesPerBuffer, - paClipOff, /* we won't output out of range samples so don't bother clipping them */ - NULL, // causes non-blocking IO - NULL ); - if( err != paNoError ) goto error1; - err = Pa_OpenStream( - &outStream, - NULL, - &test->outputParameters, - test->sampleRate, - test->framesPerBuffer, - paClipOff, /* we won't output out of range samples so don't bother clipping them */ - NULL, // causes non-blocking IO - NULL ); - if( err != paNoError ) goto error2; - - CopyStreamInfoToLoopbackContext( loopbackContext, inStream, outStream ); - - err = Pa_StartStream( outStream ); - if( err != paNoError ) goto error3; - - err = Pa_StartStream( inStream ); - if( err != paNoError ) goto error3; - - while( err == 0 ) - { - err = RecordAndPlayBlockingIO( inStream, outStream, loopbackContext ); - if( err < 0 ) goto error3; - } - - err = Pa_StopStream( inStream ); - if( err != paNoError ) goto error3; - - err = Pa_StopStream( outStream ); - if( err != paNoError ) goto error3; - - err = Pa_CloseStream( outStream ); - if( err != paNoError ) goto error2; - - err = Pa_CloseStream( inStream ); - if( err != paNoError ) goto error1; - - - return 0; - + PaStream *inStream = NULL; + PaStream *outStream = NULL; + PaError err = 0; + TestParameters *test = loopbackContext->test; + + // Use two half duplex streams. + err = Pa_OpenStream( + &inStream, + &test->inputParameters, + NULL, + test->sampleRate, + test->framesPerBuffer, + paClipOff, /* we won't output out of range samples so don't bother clipping them */ + NULL, // causes non-blocking IO + NULL ); + if( err != paNoError ) goto error1; + err = Pa_OpenStream( + &outStream, + NULL, + &test->outputParameters, + test->sampleRate, + test->framesPerBuffer, + paClipOff, /* we won't output out of range samples so don't bother clipping them */ + NULL, // causes non-blocking IO + NULL ); + if( err != paNoError ) goto error2; + + CopyStreamInfoToLoopbackContext( loopbackContext, inStream, outStream ); + + err = Pa_StartStream( outStream ); + if( err != paNoError ) goto error3; + + err = Pa_StartStream( inStream ); + if( err != paNoError ) goto error3; + + while( err == 0 ) + { + err = RecordAndPlayBlockingIO( inStream, outStream, loopbackContext ); + if( err < 0 ) goto error3; + } + + err = Pa_StopStream( inStream ); + if( err != paNoError ) goto error3; + + err = Pa_StopStream( outStream ); + if( err != paNoError ) goto error3; + + err = Pa_CloseStream( outStream ); + if( err != paNoError ) goto error2; + + err = Pa_CloseStream( inStream ); + if( err != paNoError ) goto error1; + + + return 0; + error3: - Pa_CloseStream( outStream ); + Pa_CloseStream( outStream ); error2: - Pa_CloseStream( inStream ); + Pa_CloseStream( inStream ); error1: - return err; + return err; } /*******************************************************************/ -/** +/** * Open one audio stream with non-blocking IO. * Generate sine waves on the output channels and record the input channels. * Then close the stream. @@ -619,669 +619,659 @@ error1: */ int PaQa_RunLoopbackFullDuplexBlockingIO( LoopbackContext *loopbackContext ) { - PaStream *stream = NULL; - PaError err = 0; - TestParameters *test = loopbackContext->test; - - // Use one full duplex stream. - err = Pa_OpenStream( - &stream, - &test->inputParameters, - &test->outputParameters, - test->sampleRate, - test->framesPerBuffer, - paClipOff, /* we won't output out of range samples so don't bother clipping them */ - NULL, // causes non-blocking IO - NULL ); - if( err != paNoError ) goto error1; - - CopyStreamInfoToLoopbackContext( loopbackContext, stream, stream ); - - err = Pa_StartStream( stream ); - if( err != paNoError ) goto error2; - - while( err == 0 ) - { - err = RecordAndPlayBlockingIO( stream, stream, loopbackContext ); - if( err < 0 ) goto error2; - } - - err = Pa_StopStream( stream ); - if( err != paNoError ) goto error2; - - - err = Pa_CloseStream( stream ); - if( err != paNoError ) goto error1; - - - return 0; - + PaStream *stream = NULL; + PaError err = 0; + TestParameters *test = loopbackContext->test; + + // Use one full duplex stream. + err = Pa_OpenStream( + &stream, + &test->inputParameters, + &test->outputParameters, + test->sampleRate, + test->framesPerBuffer, + paClipOff, /* we won't output out of range samples so don't bother clipping them */ + NULL, // causes non-blocking IO + NULL ); + if( err != paNoError ) goto error1; + + CopyStreamInfoToLoopbackContext( loopbackContext, stream, stream ); + + err = Pa_StartStream( stream ); + if( err != paNoError ) goto error2; + + while( err == 0 ) + { + err = RecordAndPlayBlockingIO( stream, stream, loopbackContext ); + if( err < 0 ) goto error2; + } + + err = Pa_StopStream( stream ); + if( err != paNoError ) goto error2; + + + err = Pa_CloseStream( stream ); + if( err != paNoError ) goto error1; + + + return 0; + error2: - Pa_CloseStream( stream ); + Pa_CloseStream( stream ); error1: - return err; + return err; } /*******************************************************************/ -/** +/** * Run some kind of loopback test. * @return 0 if OK or negative error. */ int PaQa_RunLoopback( LoopbackContext *loopbackContext ) { - PaError err = 0; - TestParameters *test = loopbackContext->test; - - - if( test->flags & PAQA_FLAG_TWO_STREAMS ) - { - if( test->flags & PAQA_FLAG_USE_BLOCKING_IO ) - { - err = PaQa_RunLoopbackHalfDuplexBlockingIO( loopbackContext ); - } - else - { - err = PaQa_RunLoopbackHalfDuplex( loopbackContext ); - } - } - else - { - if( test->flags & PAQA_FLAG_USE_BLOCKING_IO ) - { - err = PaQa_RunLoopbackFullDuplexBlockingIO( loopbackContext ); - } - else - { - err = PaQa_RunLoopbackFullDuplex( loopbackContext ); - } - } - - if( err != paNoError ) - { - printf("PortAudio error = %s\n", Pa_GetErrorText( err ) ); - } - return err; + PaError err = 0; + TestParameters *test = loopbackContext->test; + + + if( test->flags & PAQA_FLAG_TWO_STREAMS ) + { + if( test->flags & PAQA_FLAG_USE_BLOCKING_IO ) + { + err = PaQa_RunLoopbackHalfDuplexBlockingIO( loopbackContext ); + } + else + { + err = PaQa_RunLoopbackHalfDuplex( loopbackContext ); + } + } + else + { + if( test->flags & PAQA_FLAG_USE_BLOCKING_IO ) + { + err = PaQa_RunLoopbackFullDuplexBlockingIO( loopbackContext ); + } + else + { + err = PaQa_RunLoopbackFullDuplex( loopbackContext ); + } + } + + if( err != paNoError ) + { + printf("PortAudio error = %s\n", Pa_GetErrorText( err ) ); + } + return err; } /*******************************************************************/ static int PaQa_SaveTestResultToWaveFile( UserOptions *userOptions, PaQaRecording *recording ) { - if( userOptions->saveBadWaves ) - { - char filename[256]; + if( userOptions->saveBadWaves ) + { + char filename[256]; #ifdef WIN32 _snprintf( filename, sizeof(filename), "%s\\paloopback_%d.wav", userOptions->waveFilePath, userOptions->waveFileCount++ ); #else - snprintf( filename, sizeof(filename), "%s/paloopback_%d.wav", userOptions->waveFilePath, userOptions->waveFileCount++ ); -#endif - printf( "\"%s\", ", filename ); - return PaQa_SaveRecordingToWaveFile( recording, filename ); - } - return 0; + snprintf( filename, sizeof(filename), "%s/paloopback_%d.wav", userOptions->waveFilePath, userOptions->waveFileCount++ ); +#endif + printf( "\"%s\", ", filename ); + return PaQa_SaveRecordingToWaveFile( recording, filename ); + } + return 0; } /*******************************************************************/ static int PaQa_SetupLoopbackContext( LoopbackContext *loopbackContextPtr, TestParameters *testParams ) { - int i; - // Setup loopback context. - memset( loopbackContextPtr, 0, sizeof(LoopbackContext) ); - loopbackContextPtr->test = testParams; - for( i=0; isamplesPerFrame; i++ ) - { - int err = PaQa_InitializeRecording( &loopbackContextPtr->recordings[i], testParams->maxFrames, testParams->sampleRate ); - QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", paNoError, err ); - } - for( i=0; isamplesPerFrame; i++ ) - { - PaQa_SetupSineGenerator( &loopbackContextPtr->generators[i], PaQa_GetNthFrequency( testParams->baseFrequency, i ), - testParams->amplitude, testParams->sampleRate ); - } - loopbackContextPtr->minFramesPerBuffer = 0x0FFFFFFF; - return 0; + int i; + // Setup loopback context. + memset( loopbackContextPtr, 0, sizeof(LoopbackContext) ); + loopbackContextPtr->test = testParams; + for( i=0; isamplesPerFrame; i++ ) + { + int err = PaQa_InitializeRecording( &loopbackContextPtr->recordings[i], testParams->maxFrames, testParams->sampleRate ); + QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", paNoError, err ); + } + for( i=0; isamplesPerFrame; i++ ) + { + PaQa_SetupSineGenerator( &loopbackContextPtr->generators[i], PaQa_GetNthFrequency( testParams->baseFrequency, i ), + testParams->amplitude, testParams->sampleRate ); + } + loopbackContextPtr->minFramesPerBuffer = 0x0FFFFFFF; + return 0; error: - return -1; + return -1; } /*******************************************************************/ static void PaQa_TeardownLoopbackContext( LoopbackContext *loopbackContextPtr ) { - int i; - if( loopbackContextPtr->test != NULL ) - { - for( i=0; itest->samplesPerFrame; i++ ) - { - PaQa_TerminateRecording( &loopbackContextPtr->recordings[i] ); - } - } + int i; + if( loopbackContextPtr->test != NULL ) + { + for( i=0; itest->samplesPerFrame; i++ ) + { + PaQa_TerminateRecording( &loopbackContextPtr->recordings[i] ); + } + } } /*******************************************************************/ static void PaQa_PrintShortErrorReport( PaQaAnalysisResult *analysisResultPtr, int channel ) { - printf("channel %d ", channel); - if( analysisResultPtr->popPosition > 0 ) - { - printf("POP %0.3f at %d, ", (double)analysisResultPtr->popAmplitude, (int)analysisResultPtr->popPosition ); - } - else - { - if( analysisResultPtr->addedFramesPosition > 0 ) - { - printf("ADD %d at %d ", (int)analysisResultPtr->numAddedFrames, (int)analysisResultPtr->addedFramesPosition ); - } - - if( analysisResultPtr->droppedFramesPosition > 0 ) - { - printf("DROP %d at %d ", (int)analysisResultPtr->numDroppedFrames, (int)analysisResultPtr->droppedFramesPosition ); - } - } + printf("channel %d ", channel); + if( analysisResultPtr->popPosition > 0 ) + { + printf("POP %0.3f at %d, ", (double)analysisResultPtr->popAmplitude, (int)analysisResultPtr->popPosition ); + } + else + { + if( analysisResultPtr->addedFramesPosition > 0 ) + { + printf("ADD %d at %d ", (int)analysisResultPtr->numAddedFrames, (int)analysisResultPtr->addedFramesPosition ); + } + + if( analysisResultPtr->droppedFramesPosition > 0 ) + { + printf("DROP %d at %d ", (int)analysisResultPtr->numDroppedFrames, (int)analysisResultPtr->droppedFramesPosition ); + } + } } /*******************************************************************/ static void PaQa_PrintFullErrorReport( PaQaAnalysisResult *analysisResultPtr, int channel ) { - printf("\n=== Loopback Analysis ===================\n"); - printf(" channel: %d\n", channel ); - printf(" latency: %10.3f\n", analysisResultPtr->latency ); - printf(" amplitudeRatio: %10.3f\n", (double)analysisResultPtr->amplitudeRatio ); - printf(" popPosition: %10.3f\n", (double)analysisResultPtr->popPosition ); - printf(" popAmplitude: %10.3f\n", (double)analysisResultPtr->popAmplitude ); - printf(" num added frames: %10.3f\n", analysisResultPtr->numAddedFrames ); - printf(" added frames at: %10.3f\n", analysisResultPtr->addedFramesPosition ); - printf(" num dropped frames: %10.3f\n", analysisResultPtr->numDroppedFrames ); - printf(" dropped frames at: %10.3f\n", analysisResultPtr->droppedFramesPosition ); + printf("\n=== Loopback Analysis ===================\n"); + printf(" channel: %d\n", channel ); + printf(" latency: %10.3f\n", analysisResultPtr->latency ); + printf(" amplitudeRatio: %10.3f\n", (double)analysisResultPtr->amplitudeRatio ); + printf(" popPosition: %10.3f\n", (double)analysisResultPtr->popPosition ); + printf(" popAmplitude: %10.3f\n", (double)analysisResultPtr->popAmplitude ); + printf(" num added frames: %10.3f\n", analysisResultPtr->numAddedFrames ); + printf(" added frames at: %10.3f\n", analysisResultPtr->addedFramesPosition ); + printf(" num dropped frames: %10.3f\n", analysisResultPtr->numDroppedFrames ); + printf(" dropped frames at: %10.3f\n", analysisResultPtr->droppedFramesPosition ); } /*******************************************************************/ -/** +/** * Test loopback connection using the given parameters. * @return number of channels with glitches, or negative error. */ static int PaQa_SingleLoopBackTest( UserOptions *userOptions, TestParameters *testParams ) { - int i; - LoopbackContext loopbackContext; - PaError err = paNoError; - PaQaTestTone testTone; - PaQaAnalysisResult analysisResult; - int numBadChannels = 0; - - printf("| %5d | %6d | ", ((int)(testParams->sampleRate+0.5)), testParams->framesPerBuffer ); - fflush(stdout); - - testTone.samplesPerFrame = testParams->samplesPerFrame; - testTone.sampleRate = testParams->sampleRate; - testTone.amplitude = testParams->amplitude; - testTone.startDelay = 0; - - err = PaQa_SetupLoopbackContext( &loopbackContext, testParams ); - if( err ) return err; - - err = PaQa_RunLoopback( &loopbackContext ); - QA_ASSERT_TRUE("loopback did not run", (loopbackContext.callbackCount > 1) ); - - printf( "%7.2f %7.2f %7.2f | ", - loopbackContext.streamInfoInputLatency * 1000.0, - loopbackContext.streamInfoOutputLatency * 1000.0, - (loopbackContext.streamInfoInputLatency + loopbackContext.streamInfoOutputLatency) * 1000.0 - ); - - printf( "%4d/%4d/%4d, %4d/%4d/%4d | ", - loopbackContext.inputOverflowCount, - loopbackContext.inputUnderflowCount, - loopbackContext.inputBufferCount, - loopbackContext.outputOverflowCount, - loopbackContext.outputUnderflowCount, - loopbackContext.outputBufferCount - ); - - // Analyse recording to detect glitches. - for( i=0; isamplesPerFrame; i++ ) - { - double freq = PaQa_GetNthFrequency( testParams->baseFrequency, i ); - testTone.frequency = freq; - - PaQa_AnalyseRecording( &loopbackContext.recordings[i], &testTone, &analysisResult ); - - if( i==0 ) - { + int i; + LoopbackContext loopbackContext; + PaError err = paNoError; + PaQaTestTone testTone; + PaQaAnalysisResult analysisResult; + int numBadChannels = 0; + + printf("| %5d | %6d | ", ((int)(testParams->sampleRate+0.5)), testParams->framesPerBuffer ); + fflush(stdout); + + testTone.samplesPerFrame = testParams->samplesPerFrame; + testTone.sampleRate = testParams->sampleRate; + testTone.amplitude = testParams->amplitude; + testTone.startDelay = 0; + + err = PaQa_SetupLoopbackContext( &loopbackContext, testParams ); + if( err ) return err; + + err = PaQa_RunLoopback( &loopbackContext ); + QA_ASSERT_TRUE("loopback did not run", (loopbackContext.callbackCount > 1) ); + + printf( "%7.2f %7.2f %7.2f | ", + loopbackContext.streamInfoInputLatency * 1000.0, + loopbackContext.streamInfoOutputLatency * 1000.0, + (loopbackContext.streamInfoInputLatency + loopbackContext.streamInfoOutputLatency) * 1000.0 + ); + + printf( "%4d/%4d/%4d, %4d/%4d/%4d | ", + loopbackContext.inputOverflowCount, + loopbackContext.inputUnderflowCount, + loopbackContext.inputBufferCount, + loopbackContext.outputOverflowCount, + loopbackContext.outputUnderflowCount, + loopbackContext.outputBufferCount + ); + + // Analyse recording to detect glitches. + for( i=0; isamplesPerFrame; i++ ) + { + double freq = PaQa_GetNthFrequency( testParams->baseFrequency, i ); + testTone.frequency = freq; + + PaQa_AnalyseRecording( &loopbackContext.recordings[i], &testTone, &analysisResult ); + + if( i==0 ) + { double latencyMSec; - printf( "%4d-%4d | ", - loopbackContext.minFramesPerBuffer, - loopbackContext.maxFramesPerBuffer - ); - - latencyMSec = 1000.0 * analysisResult.latency / testParams->sampleRate; - printf("%7.2f | ", latencyMSec ); - - } - - if( analysisResult.valid ) - { - int badChannel = ( (analysisResult.popPosition > 0) - || (analysisResult.addedFramesPosition > 0) - || (analysisResult.droppedFramesPosition > 0) ); - - if( badChannel ) - { - if( userOptions->verbose ) - { - PaQa_PrintFullErrorReport( &analysisResult, i ); - } - else - { - PaQa_PrintShortErrorReport( &analysisResult, i ); - } - PaQa_SaveTestResultToWaveFile( userOptions, &loopbackContext.recordings[i] ); - } - numBadChannels += badChannel; - } - else - { - printf( "[%d] No or low signal, ampRatio = %f", i, analysisResult.amplitudeRatio ); - numBadChannels += 1; - } - - } - if( numBadChannels == 0 ) - { - printf( "OK" ); - } - - // Print the # errors so far to make it easier to see where the error occured. - printf( " - #errs = %d\n", g_testsFailed ); - - PaQa_TeardownLoopbackContext( &loopbackContext ); - if( numBadChannels > 0 ) - { - g_testsFailed += 1; - } - return numBadChannels; - + printf( "%4d-%4d | ", + loopbackContext.minFramesPerBuffer, + loopbackContext.maxFramesPerBuffer + ); + + latencyMSec = 1000.0 * analysisResult.latency / testParams->sampleRate; + printf("%7.2f | ", latencyMSec ); + + } + + if( analysisResult.valid ) + { + int badChannel = ( (analysisResult.popPosition > 0) + || (analysisResult.addedFramesPosition > 0) + || (analysisResult.droppedFramesPosition > 0) ); + + if( badChannel ) + { + if( userOptions->verbose ) + { + PaQa_PrintFullErrorReport( &analysisResult, i ); + } + else + { + PaQa_PrintShortErrorReport( &analysisResult, i ); + } + PaQa_SaveTestResultToWaveFile( userOptions, &loopbackContext.recordings[i] ); + } + numBadChannels += badChannel; + } + else + { + printf( "[%d] No or low signal, ampRatio = %f", i, analysisResult.amplitudeRatio ); + numBadChannels += 1; + } + + } + if( numBadChannels == 0 ) + { + printf( "OK" ); + } + + // Print the # errors so far to make it easier to see where the error occurred. + printf( " - #errs = %d\n", g_testsFailed ); + + PaQa_TeardownLoopbackContext( &loopbackContext ); + if( numBadChannels > 0 ) + { + g_testsFailed += 1; + } + return numBadChannels; + error: - PaQa_TeardownLoopbackContext( &loopbackContext ); - printf( "\n" ); - g_testsFailed += 1; - return err; + PaQa_TeardownLoopbackContext( &loopbackContext ); + printf( "\n" ); + g_testsFailed += 1; + return err; } /*******************************************************************/ -static void PaQa_SetDefaultTestParameters( TestParameters *testParamsPtr, PaDeviceIndex inputDevice, PaDeviceIndex outputDevice ) +static void PaQa_MakeTestParameters( TestParameters *testParamsPtr, PaDeviceIndex inputDevice, PaDeviceIndex outputDevice, const UserOptions *userOptions ) { - memset( testParamsPtr, 0, sizeof(TestParameters) ); - - testParamsPtr->samplesPerFrame = 2; - testParamsPtr->amplitude = 0.5; - testParamsPtr->sampleRate = 44100; - testParamsPtr->maxFrames = (int) (PAQA_TEST_DURATION * testParamsPtr->sampleRate); - testParamsPtr->framesPerBuffer = DEFAULT_FRAMES_PER_BUFFER; - testParamsPtr->baseFrequency = 200.0; - testParamsPtr->flags = PAQA_FLAG_TWO_STREAMS; + memset( testParamsPtr, 0, sizeof(TestParameters) ); + + testParamsPtr->samplesPerFrame = 2; + testParamsPtr->amplitude = 0.5; + testParamsPtr->sampleRate = 44100; + testParamsPtr->maxFrames = (int) (PAQA_TEST_DURATION * testParamsPtr->sampleRate); + testParamsPtr->framesPerBuffer = DEFAULT_FRAMES_PER_BUFFER; + testParamsPtr->baseFrequency = 200.0; + testParamsPtr->flags = PAQA_FLAG_TWO_STREAMS; testParamsPtr->streamFlags = paClipOff; /* we won't output out of range samples so don't bother clipping them */ - - testParamsPtr->inputParameters.device = inputDevice; - testParamsPtr->inputParameters.sampleFormat = paFloat32; - testParamsPtr->inputParameters.channelCount = testParamsPtr->samplesPerFrame; - testParamsPtr->inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputDevice )->defaultLowInputLatency; - //testParamsPtr->inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputDevice )->defaultHighInputLatency; - - testParamsPtr->outputParameters.device = outputDevice; - testParamsPtr->outputParameters.sampleFormat = paFloat32; - testParamsPtr->outputParameters.channelCount = testParamsPtr->samplesPerFrame; - testParamsPtr->outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputDevice )->defaultLowOutputLatency; - //testParamsPtr->outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputDevice )->defaultHighOutputLatency; -} -/*******************************************************************/ -static void PaQa_OverrideTestParameters( TestParameters *testParamsPtr, UserOptions *userOptions ) -{ - // Check to see if a specific value was requested. - if( userOptions->sampleRate >= 0 ) - { - testParamsPtr->sampleRate = userOptions->sampleRate; - testParamsPtr->maxFrames = (int) (PAQA_TEST_DURATION * testParamsPtr->sampleRate); - } - if( userOptions->framesPerBuffer >= 0 ) - { - testParamsPtr->framesPerBuffer = userOptions->framesPerBuffer; - } - if( userOptions->inputLatency >= 0 ) - { - testParamsPtr->inputParameters.suggestedLatency = userOptions->inputLatency * 0.001; - } - if( userOptions->outputLatency >= 0 ) - { - testParamsPtr->outputParameters.suggestedLatency = userOptions->outputLatency * 0.001; - } - printf( " Running with suggested latency (msec): input = %5.2f, out = %5.2f\n", - (testParamsPtr->inputParameters.suggestedLatency * 1000.0), - (testParamsPtr->outputParameters.suggestedLatency * 1000.0) ); + testParamsPtr->inputParameters.device = inputDevice; + testParamsPtr->inputParameters.sampleFormat = paFloat32; + testParamsPtr->inputParameters.channelCount = testParamsPtr->samplesPerFrame; + testParamsPtr->inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputDevice )->defaultLowInputLatency; + //testParamsPtr->inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputDevice )->defaultHighInputLatency; + + testParamsPtr->outputParameters.device = outputDevice; + testParamsPtr->outputParameters.sampleFormat = paFloat32; + testParamsPtr->outputParameters.channelCount = testParamsPtr->samplesPerFrame; + testParamsPtr->outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputDevice )->defaultLowOutputLatency; + //testParamsPtr->outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputDevice )->defaultHighOutputLatency; + + // Check to see if a specific value was requested. + if( userOptions->sampleRate >= 0 ) + { + testParamsPtr->sampleRate = userOptions->sampleRate; + testParamsPtr->maxFrames = (int) (PAQA_TEST_DURATION * testParamsPtr->sampleRate); + } + if( userOptions->framesPerBuffer >= 0 ) + { + testParamsPtr->framesPerBuffer = userOptions->framesPerBuffer; + } + if( userOptions->inputLatency >= 0 ) + { + testParamsPtr->inputParameters.suggestedLatency = userOptions->inputLatency * 0.001; + } + if( userOptions->outputLatency >= 0 ) + { + testParamsPtr->outputParameters.suggestedLatency = userOptions->outputLatency * 0.001; + } + printf( " Running with suggested latency (msec): input = %5.2f, out = %5.2f\n", + (testParamsPtr->inputParameters.suggestedLatency * 1000.0), + (testParamsPtr->outputParameters.suggestedLatency * 1000.0) ); } /*******************************************************************/ -/** +/** * Run a series of tests on this loopback connection. * @return number of bad channel results */ static int PaQa_AnalyzeLoopbackConnection( UserOptions *userOptions, PaDeviceIndex inputDevice, PaDeviceIndex outputDevice ) { - int iFlags; - int iRate; - int iSize; - int iFormat; - int savedValue; - TestParameters testParams; - const PaDeviceInfo *inputDeviceInfo = Pa_GetDeviceInfo( inputDevice ); - const PaDeviceInfo *outputDeviceInfo = Pa_GetDeviceInfo( outputDevice ); + int iFlags; + int iRate; + int iSize; + int iFormat; + TestParameters testParams; + const PaDeviceInfo *inputDeviceInfo = Pa_GetDeviceInfo( inputDevice ); + const PaDeviceInfo *outputDeviceInfo = Pa_GetDeviceInfo( outputDevice ); int totalBadChannels = 0; - // test half duplex first because it is more likely to work. - int flagSettings[] = { PAQA_FLAG_TWO_STREAMS, 0 }; - int numFlagSettings = (sizeof(flagSettings)/sizeof(int)); - - double sampleRates[] = { 8000.0, 11025.0, 16000.0, 22050.0, 32000.0, 44100.0, 48000.0, 96000.0 }; - int numRates = (sizeof(sampleRates)/sizeof(double)); - - // framesPerBuffer==0 means PA decides on the buffer size. - int framesPerBuffers[] = { 0, 16, 32, 40, 64, 100, 128, 256, 512, 1024 }; - int numBufferSizes = (sizeof(framesPerBuffers)/sizeof(int)); - - PaSampleFormat sampleFormats[] = { paFloat32, paUInt8, paInt8, paInt16, paInt32 }; - const char *sampleFormatNames[] = { "paFloat32", "paUInt8", "paInt8", "paInt16", "paInt32" }; - int numSampleFormats = (sizeof(sampleFormats)/sizeof(PaSampleFormat)); - + // test half duplex first because it is more likely to work. + int flagSettings[] = { PAQA_FLAG_TWO_STREAMS, 0 }; + int numFlagSettings = (sizeof(flagSettings)/sizeof(int)); + + double sampleRates[] = { 8000.0, 11025.0, 16000.0, 22050.0, 32000.0, 44100.0, 48000.0, 96000.0 }; + int numRates = (sizeof(sampleRates)/sizeof(double)); + + // framesPerBuffer==0 means PA decides on the buffer size. + int framesPerBuffers[] = { 0, 16, 32, 40, 64, 100, 128, 256, 512, 1024 }; + int numBufferSizes = (sizeof(framesPerBuffers)/sizeof(int)); + + PaSampleFormat sampleFormats[] = { paFloat32, paUInt8, paInt8, paInt16, paInt32 }; + const char *sampleFormatNames[] = { "paFloat32", "paUInt8", "paInt8", "paInt16", "paInt32" }; + int numSampleFormats = (sizeof(sampleFormats)/sizeof(PaSampleFormat)); + printf( "=============== Analysing Loopback %d to %d =====================\n", outputDevice, inputDevice ); - printf( " Devices: %s => %s\n", outputDeviceInfo->name, inputDeviceInfo->name); - - PaQa_SetDefaultTestParameters( &testParams, inputDevice, outputDevice ); - - PaQa_OverrideTestParameters( &testParams, userOptions ); - - // Loop though combinations of audio parameters. - for( iFlags=0; iFlagssampleRate < 0 ) - { - savedValue = testParams.sampleRate; - for( iRate=0; iRate %s\n", outputDeviceInfo->name, inputDeviceInfo->name); + + PaQa_MakeTestParameters( &testParams, inputDevice, outputDevice, userOptions ); + + // Loop though combinations of audio parameters. + for( iFlags=0; iFlagssampleRate < 0 ) + { + for( iRate=0; iRateframesPerBuffer < 0 ) - { - savedValue = testParams.framesPerBuffer; - for( iSize=0; iSizeframesPerBuffer < 0 ) + { + for( iSize=0; iSizetest; - - // Start in the middle assuming past latency. - int startFrame = testParamsPtr->maxFrames/2; - int numFrames = testParamsPtr->maxFrames/2; - - // Check to see if the signal is clipped. - double amplitudeLeft = PaQa_MeasureSineAmplitudeBySlope( &loopbackContextPtr->recordings[0], - testParamsPtr->baseFrequency, testParamsPtr->sampleRate, - startFrame, numFrames ); - double gainLeft = amplitudeLeft / testParamsPtr->amplitude; - double amplitudeRight = PaQa_MeasureSineAmplitudeBySlope( &loopbackContextPtr->recordings[1], - testParamsPtr->baseFrequency, testParamsPtr->sampleRate, - startFrame, numFrames ); - double gainRight = amplitudeLeft / testParamsPtr->amplitude; - printf(" Loop gain: left = %f, right = %f\n", gainLeft, gainRight ); - - if( (amplitudeLeft > 1.0 ) || (amplitudeRight > 1.0) ) - { - printf("ERROR - loop gain is too high. Should be around than 1.0. Please lower output level and/or input gain.\n" ); - clipped = 1; - } - return clipped; + int clipped = 0; + TestParameters *testParamsPtr = loopbackContextPtr->test; + + // Start in the middle assuming past latency. + int startFrame = testParamsPtr->maxFrames/2; + int numFrames = testParamsPtr->maxFrames/2; + + // Check to see if the signal is clipped. + double amplitudeLeft = PaQa_MeasureSineAmplitudeBySlope( &loopbackContextPtr->recordings[0], + testParamsPtr->baseFrequency, testParamsPtr->sampleRate, + startFrame, numFrames ); + double gainLeft = amplitudeLeft / testParamsPtr->amplitude; + double amplitudeRight = PaQa_MeasureSineAmplitudeBySlope( &loopbackContextPtr->recordings[1], + testParamsPtr->baseFrequency, testParamsPtr->sampleRate, + startFrame, numFrames ); + double gainRight = amplitudeLeft / testParamsPtr->amplitude; + printf(" Loop gain: left = %f, right = %f\n", gainLeft, gainRight ); + + if( (amplitudeLeft > 1.0 ) || (amplitudeRight > 1.0) ) + { + printf("ERROR - loop gain is too high. Should be around than 1.0. Please lower output level and/or input gain.\n" ); + clipped = 1; + } + return clipped; } /*******************************************************************/ int PaQa_MeasureBackgroundNoise( LoopbackContext *loopbackContextPtr, double *rmsPtr ) { - int result = 0; - *rmsPtr = 0.0; - // Rewind so we can record some input. - loopbackContextPtr->recordings[0].numFrames = 0; - loopbackContextPtr->recordings[1].numFrames = 0; - result = PaQa_RunInputOnly( loopbackContextPtr ); - if( result == 0 ) - { - double leftRMS = PaQa_MeasureRootMeanSquare( loopbackContextPtr->recordings[0].buffer, - loopbackContextPtr->recordings[0].numFrames ); - double rightRMS = PaQa_MeasureRootMeanSquare( loopbackContextPtr->recordings[1].buffer, - loopbackContextPtr->recordings[1].numFrames ); - *rmsPtr = (leftRMS + rightRMS) / 2.0; - } - return result; + int result = 0; + *rmsPtr = 0.0; + // Rewind so we can record some input. + loopbackContextPtr->recordings[0].numFrames = 0; + loopbackContextPtr->recordings[1].numFrames = 0; + result = PaQa_RunInputOnly( loopbackContextPtr ); + if( result == 0 ) + { + double leftRMS = PaQa_MeasureRootMeanSquare( loopbackContextPtr->recordings[0].buffer, + loopbackContextPtr->recordings[0].numFrames ); + double rightRMS = PaQa_MeasureRootMeanSquare( loopbackContextPtr->recordings[1].buffer, + loopbackContextPtr->recordings[1].numFrames ); + *rmsPtr = (leftRMS + rightRMS) / 2.0; + } + return result; } /*******************************************************************/ -/** +/** * Output a sine wave then try to detect it on input. * * @return 1 if loopback connected, 0 if not, or negative error. */ int PaQa_CheckForLoopBack( UserOptions *userOptions, PaDeviceIndex inputDevice, PaDeviceIndex outputDevice ) { - TestParameters testParams; - LoopbackContext loopbackContext; - const PaDeviceInfo *inputDeviceInfo; - const PaDeviceInfo *outputDeviceInfo; - PaError err = paNoError; - double minAmplitude; - int loopbackIsConnected; + TestParameters testParams; + LoopbackContext loopbackContext; + const PaDeviceInfo *inputDeviceInfo; + const PaDeviceInfo *outputDeviceInfo; + PaError err = paNoError; + double minAmplitude; + int loopbackIsConnected; int startFrame, numFrames; double magLeft, magRight; - inputDeviceInfo = Pa_GetDeviceInfo( inputDevice ); - if( inputDeviceInfo == NULL ) - { - printf("ERROR - Pa_GetDeviceInfo for input returned NULL.\n"); - return paInvalidDevice; - } - if( inputDeviceInfo->maxInputChannels < 2 ) - { - return 0; - } - - outputDeviceInfo = Pa_GetDeviceInfo( outputDevice ); - if( outputDeviceInfo == NULL ) - { - printf("ERROR - Pa_GetDeviceInfo for output returned NULL.\n"); - return paInvalidDevice; - } - if( outputDeviceInfo->maxOutputChannels < 2 ) - { - return 0; - } - - printf( "Look for loopback cable between \"%s\" => \"%s\"\n", outputDeviceInfo->name, inputDeviceInfo->name); - - printf( " Default suggested input latency (msec): low = %5.2f, high = %5.2f\n", - (inputDeviceInfo->defaultLowInputLatency * 1000.0), - (inputDeviceInfo->defaultHighInputLatency * 1000.0) ); - printf( " Default suggested output latency (msec): low = %5.2f, high = %5.2f\n", - (outputDeviceInfo->defaultLowOutputLatency * 1000.0), - (outputDeviceInfo->defaultHighOutputLatency * 1000.0) ); - - PaQa_SetDefaultTestParameters( &testParams, inputDevice, outputDevice ); - - PaQa_OverrideTestParameters( &testParams, userOptions ); - - testParams.maxFrames = (int) (LOOPBACK_DETECTION_DURATION_SECONDS * testParams.sampleRate); - minAmplitude = testParams.amplitude / 4.0; - - // Check to see if the selected formats are supported. - if( Pa_IsFormatSupported( &testParams.inputParameters, NULL, testParams.sampleRate ) != paFormatIsSupported ) - { - printf( "Input not supported for this format!\n" ); - return 0; - } - if( Pa_IsFormatSupported( NULL, &testParams.outputParameters, testParams.sampleRate ) != paFormatIsSupported ) - { - printf( "Output not supported for this format!\n" ); - return 0; - } - - PaQa_SetupLoopbackContext( &loopbackContext, &testParams ); - - if( inputDevice == outputDevice ) - { - // Use full duplex if checking for loopback on one device. - testParams.flags &= ~PAQA_FLAG_TWO_STREAMS; - } - else - { - // Use half duplex if checking for loopback on two different device. - testParams.flags = PAQA_FLAG_TWO_STREAMS; - } - err = PaQa_RunLoopback( &loopbackContext ); - QA_ASSERT_TRUE("loopback detection callback did not run", (loopbackContext.callbackCount > 1) ); - - // Analyse recording to see if we captured the output. - // Start in the middle assuming past latency. - startFrame = testParams.maxFrames/2; - numFrames = testParams.maxFrames/2; - magLeft = PaQa_CorrelateSine( &loopbackContext.recordings[0], - loopbackContext.generators[0].frequency, - testParams.sampleRate, - startFrame, numFrames, NULL ); - magRight = PaQa_CorrelateSine( &loopbackContext.recordings[1], - loopbackContext.generators[1].frequency, - testParams.sampleRate, - startFrame, numFrames, NULL ); - printf(" Amplitudes: left = %f, right = %f\n", magLeft, magRight ); - - // Check for backwards cable. + inputDeviceInfo = Pa_GetDeviceInfo( inputDevice ); + if( inputDeviceInfo == NULL ) + { + printf("ERROR - Pa_GetDeviceInfo for input returned NULL.\n"); + return paInvalidDevice; + } + if( inputDeviceInfo->maxInputChannels < 2 ) + { + return 0; + } + + outputDeviceInfo = Pa_GetDeviceInfo( outputDevice ); + if( outputDeviceInfo == NULL ) + { + printf("ERROR - Pa_GetDeviceInfo for output returned NULL.\n"); + return paInvalidDevice; + } + if( outputDeviceInfo->maxOutputChannels < 2 ) + { + return 0; + } + + printf( "Look for loopback cable between \"%s\" => \"%s\"\n", outputDeviceInfo->name, inputDeviceInfo->name); + + printf( " Default suggested input latency (msec): low = %5.2f, high = %5.2f\n", + (inputDeviceInfo->defaultLowInputLatency * 1000.0), + (inputDeviceInfo->defaultHighInputLatency * 1000.0) ); + printf( " Default suggested output latency (msec): low = %5.2f, high = %5.2f\n", + (outputDeviceInfo->defaultLowOutputLatency * 1000.0), + (outputDeviceInfo->defaultHighOutputLatency * 1000.0) ); + + PaQa_MakeTestParameters( &testParams, inputDevice, outputDevice, userOptions ); + + testParams.maxFrames = (int) (LOOPBACK_DETECTION_DURATION_SECONDS * testParams.sampleRate); + minAmplitude = testParams.amplitude / 4.0; + + // Check to see if the selected formats are supported. + if( Pa_IsFormatSupported( &testParams.inputParameters, NULL, testParams.sampleRate ) != paFormatIsSupported ) + { + printf( "Input not supported for this format!\n" ); + return 0; + } + if( Pa_IsFormatSupported( NULL, &testParams.outputParameters, testParams.sampleRate ) != paFormatIsSupported ) + { + printf( "Output not supported for this format!\n" ); + return 0; + } + + PaQa_SetupLoopbackContext( &loopbackContext, &testParams ); + + if( inputDevice == outputDevice ) + { + // Use full duplex if checking for loopback on one device. + testParams.flags &= ~PAQA_FLAG_TWO_STREAMS; + } + else + { + // Use half duplex if checking for loopback on two different device. + testParams.flags = PAQA_FLAG_TWO_STREAMS; + } + err = PaQa_RunLoopback( &loopbackContext ); + QA_ASSERT_TRUE("loopback detection callback did not run", (loopbackContext.callbackCount > 1) ); + + // Analyse recording to see if we captured the output. + // Start in the middle assuming past latency. + startFrame = testParams.maxFrames/2; + numFrames = testParams.maxFrames/2; + magLeft = PaQa_CorrelateSine( &loopbackContext.recordings[0], + loopbackContext.generators[0].frequency, + testParams.sampleRate, + startFrame, numFrames, NULL ); + magRight = PaQa_CorrelateSine( &loopbackContext.recordings[1], + loopbackContext.generators[1].frequency, + testParams.sampleRate, + startFrame, numFrames, NULL ); + printf(" Amplitudes: left = %f, right = %f\n", magLeft, magRight ); + + // Check for backwards cable. loopbackIsConnected = ((magLeft > minAmplitude) && (magRight > minAmplitude)); - if( !loopbackIsConnected ) - { - double magLeftReverse = PaQa_CorrelateSine( &loopbackContext.recordings[0], - loopbackContext.generators[1].frequency, - testParams.sampleRate, - startFrame, numFrames, NULL ); - - double magRightReverse = PaQa_CorrelateSine( &loopbackContext.recordings[1], - loopbackContext.generators[0].frequency, - testParams.sampleRate, - startFrame, numFrames, NULL ); - - if ((magLeftReverse > minAmplitude) && (magRightReverse>minAmplitude)) - { - printf("ERROR - You seem to have the left and right channels swapped on the loopback cable!\n"); - } - } - else - { - double rms = 0.0; - if( PaQa_CheckForClippedLoopback( &loopbackContext ) ) - { - // Clipped so don't use this loopback. - loopbackIsConnected = 0; - } - - err = PaQa_MeasureBackgroundNoise( &loopbackContext, &rms ); - printf(" Background noise = %f\n", rms ); - if( err ) - { - printf("ERROR - Could not measure background noise on this input!\n"); - loopbackIsConnected = 0; - } - else if( rms > MAX_BACKGROUND_NOISE_RMS ) - { - printf("ERROR - There is too much background noise on this input!\n"); - loopbackIsConnected = 0; - } - } - - PaQa_TeardownLoopbackContext( &loopbackContext ); - return loopbackIsConnected; - + if( !loopbackIsConnected ) + { + double magLeftReverse = PaQa_CorrelateSine( &loopbackContext.recordings[0], + loopbackContext.generators[1].frequency, + testParams.sampleRate, + startFrame, numFrames, NULL ); + + double magRightReverse = PaQa_CorrelateSine( &loopbackContext.recordings[1], + loopbackContext.generators[0].frequency, + testParams.sampleRate, + startFrame, numFrames, NULL ); + + if ((magLeftReverse > minAmplitude) && (magRightReverse>minAmplitude)) + { + printf("ERROR - You seem to have the left and right channels swapped on the loopback cable!\n"); + } + } + else + { + double rms = 0.0; + if( PaQa_CheckForClippedLoopback( &loopbackContext ) ) + { + // Clipped so don't use this loopback. + loopbackIsConnected = 0; + } + + err = PaQa_MeasureBackgroundNoise( &loopbackContext, &rms ); + printf(" Background noise = %f\n", rms ); + if( err ) + { + printf("ERROR - Could not measure background noise on this input!\n"); + loopbackIsConnected = 0; + } + else if( rms > MAX_BACKGROUND_NOISE_RMS ) + { + printf("ERROR - There is too much background noise on this input!\n"); + loopbackIsConnected = 0; + } + } + + PaQa_TeardownLoopbackContext( &loopbackContext ); + return loopbackIsConnected; + error: - PaQa_TeardownLoopbackContext( &loopbackContext ); - return err; + PaQa_TeardownLoopbackContext( &loopbackContext ); + return err; } /*******************************************************************/ @@ -1289,313 +1279,313 @@ error: * If there is a loopback connection then run the analysis. */ static int CheckLoopbackAndScan( UserOptions *userOptions, - PaDeviceIndex iIn, PaDeviceIndex iOut ) + PaDeviceIndex iIn, PaDeviceIndex iOut ) { - int loopbackConnected = PaQa_CheckForLoopBack( userOptions, iIn, iOut ); - if( loopbackConnected > 0 ) - { - PaQa_AnalyzeLoopbackConnection( userOptions, iIn, iOut ); - return 1; - } - return 0; + int loopbackConnected = PaQa_CheckForLoopBack( userOptions, iIn, iOut ); + if( loopbackConnected > 0 ) + { + PaQa_AnalyzeLoopbackConnection( userOptions, iIn, iOut ); + return 1; + } + return 0; } - + /*******************************************************************/ /** * Scan every combination of output to input device. * If a loopback is found the analyse the combination. - * The scan can be overriden using the -i and -o command line options. + * The scan can be overridden using the -i and -o command line options. */ static int ScanForLoopback(UserOptions *userOptions) { - PaDeviceIndex iIn,iOut; - int numLoopbacks = 0; + PaDeviceIndex iIn,iOut; + int numLoopbacks = 0; int numDevices; - numDevices = Pa_GetDeviceCount(); - - // If both devices are specified then just use that combination. - if ((userOptions->inputDevice >= 0) && (userOptions->outputDevice >= 0)) - { - numLoopbacks += CheckLoopbackAndScan( userOptions, userOptions->inputDevice, userOptions->outputDevice ); - } - else if (userOptions->inputDevice >= 0) - { - // Just scan for output. - for( iOut=0; iOutinputDevice, iOut ); - } - } - else if (userOptions->outputDevice >= 0) - { - // Just scan for input. - for( iIn=0; iInoutputDevice ); - } - } - else - { - // Scan both. - for( iOut=0; iOut 0) ); - return numLoopbacks; - + numDevices = Pa_GetDeviceCount(); + + // If both devices are specified then just use that combination. + if ((userOptions->inputDevice >= 0) && (userOptions->outputDevice >= 0)) + { + numLoopbacks += CheckLoopbackAndScan( userOptions, userOptions->inputDevice, userOptions->outputDevice ); + } + else if (userOptions->inputDevice >= 0) + { + // Just scan for output. + for( iOut=0; iOutinputDevice, iOut ); + } + } + else if (userOptions->outputDevice >= 0) + { + // Just scan for input. + for( iIn=0; iInoutputDevice ); + } + } + else + { + // Scan both. + for( iOut=0; iOut 0) ); + return numLoopbacks; + error: - return -1; + return -1; } /*==========================================================================================*/ int TestSampleFormatConversion( void ) { - int i; - const float floatInput[] = { 1.0, 0.5, -0.5, -1.0 }; - - const char charInput[] = { 127, 64, -64, -128 }; - const unsigned char ucharInput[] = { 255, 128+64, 64, 0 }; - const short shortInput[] = { 32767, 32768/2, -32768/2, -32768 }; - const int intInput[] = { 2147483647, 2147483647/2, -1073741824 /*-2147483648/2 doesn't work in msvc*/, -2147483648 }; - - float floatOutput[4]; - short shortOutput[4]; - int intOutput[4]; - unsigned char ucharOutput[4]; - char charOutput[4]; - - QA_ASSERT_EQUALS("int must be 32-bit", 4, (int) sizeof(int) ); - QA_ASSERT_EQUALS("short must be 16-bit", 2, (int) sizeof(short) ); - - // from Float ====== - PaQa_ConvertFromFloat( floatInput, 4, paUInt8, ucharOutput ); - for( i=0; i<4; i++ ) - { - QA_ASSERT_CLOSE_INT( "paFloat32 -> paUInt8 -> error", ucharInput[i], ucharOutput[i], 1 ); - } - - PaQa_ConvertFromFloat( floatInput, 4, paInt8, charOutput ); - for( i=0; i<4; i++ ) - { - QA_ASSERT_CLOSE_INT( "paFloat32 -> paInt8 -> error", charInput[i], charOutput[i], 1 ); - } - - PaQa_ConvertFromFloat( floatInput, 4, paInt16, shortOutput ); - for( i=0; i<4; i++ ) - { - QA_ASSERT_CLOSE_INT( "paFloat32 -> paInt16 error", shortInput[i], shortOutput[i], 1 ); - } - - PaQa_ConvertFromFloat( floatInput, 4, paInt32, intOutput ); - for( i=0; i<4; i++ ) - { - QA_ASSERT_CLOSE_INT( "paFloat32 -> paInt32 error", intInput[i], intOutput[i], 0x00010000 ); - } - - - // to Float ====== - memset( floatOutput, 0, sizeof(floatOutput) ); - PaQa_ConvertToFloat( ucharInput, 4, paUInt8, floatOutput ); - for( i=0; i<4; i++ ) - { - QA_ASSERT_CLOSE( "paUInt8 -> paFloat32 error", floatInput[i], floatOutput[i], 0.01 ); - } - - memset( floatOutput, 0, sizeof(floatOutput) ); - PaQa_ConvertToFloat( charInput, 4, paInt8, floatOutput ); - for( i=0; i<4; i++ ) - { - QA_ASSERT_CLOSE( "paInt8 -> paFloat32 error", floatInput[i], floatOutput[i], 0.01 ); - } - - memset( floatOutput, 0, sizeof(floatOutput) ); - PaQa_ConvertToFloat( shortInput, 4, paInt16, floatOutput ); - for( i=0; i<4; i++ ) - { - QA_ASSERT_CLOSE( "paInt16 -> paFloat32 error", floatInput[i], floatOutput[i], 0.001 ); - } - - memset( floatOutput, 0, sizeof(floatOutput) ); - PaQa_ConvertToFloat( intInput, 4, paInt32, floatOutput ); - for( i=0; i<4; i++ ) - { - QA_ASSERT_CLOSE( "paInt32 -> paFloat32 error", floatInput[i], floatOutput[i], 0.00001 ); - } - - return 0; - + int i; + const float floatInput[] = { 1.0, 0.5, -0.5, -1.0 }; + + const char charInput[] = { 127, 64, -64, -128 }; + const unsigned char ucharInput[] = { 255, 128+64, 64, 0 }; + const short shortInput[] = { 32767, 32768/2, -32768/2, -32768 }; + const int intInput[] = { 2147483647, 2147483647/2, -1073741824 /*-2147483648/2 doesn't work in msvc*/, -2147483648 }; + + float floatOutput[4]; + short shortOutput[4]; + int intOutput[4]; + unsigned char ucharOutput[4]; + char charOutput[4]; + + QA_ASSERT_EQUALS("int must be 32-bit", 4, (int) sizeof(int) ); + QA_ASSERT_EQUALS("short must be 16-bit", 2, (int) sizeof(short) ); + + // from Float ====== + PaQa_ConvertFromFloat( floatInput, 4, paUInt8, ucharOutput ); + for( i=0; i<4; i++ ) + { + QA_ASSERT_CLOSE_INT( "paFloat32 -> paUInt8 -> error", ucharInput[i], ucharOutput[i], 1 ); + } + + PaQa_ConvertFromFloat( floatInput, 4, paInt8, charOutput ); + for( i=0; i<4; i++ ) + { + QA_ASSERT_CLOSE_INT( "paFloat32 -> paInt8 -> error", charInput[i], charOutput[i], 1 ); + } + + PaQa_ConvertFromFloat( floatInput, 4, paInt16, shortOutput ); + for( i=0; i<4; i++ ) + { + QA_ASSERT_CLOSE_INT( "paFloat32 -> paInt16 error", shortInput[i], shortOutput[i], 1 ); + } + + PaQa_ConvertFromFloat( floatInput, 4, paInt32, intOutput ); + for( i=0; i<4; i++ ) + { + QA_ASSERT_CLOSE_INT( "paFloat32 -> paInt32 error", intInput[i], intOutput[i], 0x00010000 ); + } + + + // to Float ====== + memset( floatOutput, 0, sizeof(floatOutput) ); + PaQa_ConvertToFloat( ucharInput, 4, paUInt8, floatOutput ); + for( i=0; i<4; i++ ) + { + QA_ASSERT_CLOSE( "paUInt8 -> paFloat32 error", floatInput[i], floatOutput[i], 0.01 ); + } + + memset( floatOutput, 0, sizeof(floatOutput) ); + PaQa_ConvertToFloat( charInput, 4, paInt8, floatOutput ); + for( i=0; i<4; i++ ) + { + QA_ASSERT_CLOSE( "paInt8 -> paFloat32 error", floatInput[i], floatOutput[i], 0.01 ); + } + + memset( floatOutput, 0, sizeof(floatOutput) ); + PaQa_ConvertToFloat( shortInput, 4, paInt16, floatOutput ); + for( i=0; i<4; i++ ) + { + QA_ASSERT_CLOSE( "paInt16 -> paFloat32 error", floatInput[i], floatOutput[i], 0.001 ); + } + + memset( floatOutput, 0, sizeof(floatOutput) ); + PaQa_ConvertToFloat( intInput, 4, paInt32, floatOutput ); + for( i=0; i<4; i++ ) + { + QA_ASSERT_CLOSE( "paInt32 -> paFloat32 error", floatInput[i], floatOutput[i], 0.00001 ); + } + + return 0; + error: - return -1; + return -1; } /*******************************************************************/ void usage( const char *name ) { - printf("%s [-i# -o# -l# -r# -s# -m -w -dDir]\n", name); - printf(" -i# - Input device ID. Will scan for loopback cable if not specified.\n"); - printf(" -o# - Output device ID. Will scan for loopback if not specified.\n"); - printf(" -l# - Latency for both input and output in milliseconds.\n"); - printf(" --inputLatency # Input latency in milliseconds.\n"); - printf(" --outputLatency # Output latency in milliseconds.\n"); - printf(" -r# - Sample Rate in Hz. Will use multiple common rates if not specified.\n"); - printf(" -s# - Size of callback buffer in frames, framesPerBuffer. Will use common values if not specified.\n"); - printf(" -w - Save bad recordings in a WAV file.\n"); - printf(" -dDir - Path for Directory for WAV files. Default is current directory.\n"); - printf(" -m - Just test the DSP Math code and not the audio devices.\n"); - printf(" -v - Verbose reports.\n"); + printf("%s [-i# -o# -l# -r# -s# -m -w -dDir]\n", name); + printf(" -i# - Input device ID. Will scan for loopback cable if not specified.\n"); + printf(" -o# - Output device ID. Will scan for loopback if not specified.\n"); + printf(" -l# - Latency for both input and output in milliseconds.\n"); + printf(" --inputLatency # Input latency in milliseconds.\n"); + printf(" --outputLatency # Output latency in milliseconds.\n"); + printf(" -r# - Sample Rate in Hz. Will use multiple common rates if not specified.\n"); + printf(" -s# - Size of callback buffer in frames, framesPerBuffer. Will use common values if not specified.\n"); + printf(" -w - Save bad recordings in a WAV file.\n"); + printf(" -dDir - Path for Directory for WAV files. Default is current directory.\n"); + printf(" -m - Just test the DSP Math code and not the audio devices.\n"); + printf(" -v - Verbose reports.\n"); } /*******************************************************************/ int main( int argc, char **argv ) { int i; - UserOptions userOptions; - int result = 0; - int justMath = 0; + UserOptions userOptions; + int result = 0; + int justMath = 0; char *executableName = argv[0]; - printf("PortAudio LoopBack Test built " __DATE__ " at " __TIME__ "\n"); - - if( argc > 1 ){ - printf("running with arguments:"); - for(i=1; i < argc; ++i ) - printf(" %s", argv[i] ); - printf("\n"); - }else{ - printf("running with no arguments\n"); - } - - memset(&userOptions, 0, sizeof(userOptions)); - userOptions.inputDevice = paNoDevice; - userOptions.outputDevice = paNoDevice; - userOptions.sampleRate = -1; - userOptions.framesPerBuffer = -1; - userOptions.inputLatency = -1; - userOptions.outputLatency = -1; - userOptions.waveFilePath = "."; - - // Process arguments. Skip name of executable. - i = 1; - while( i 1 ){ + printf("running with arguments:"); + for(i=1; i < argc; ++i ) + printf(" %s", argv[i] ); + printf("\n"); + }else{ + printf("running with no arguments\n"); + } + + memset(&userOptions, 0, sizeof(userOptions)); + userOptions.inputDevice = paNoDevice; + userOptions.outputDevice = paNoDevice; + userOptions.sampleRate = -1; + userOptions.framesPerBuffer = -1; + userOptions.inputLatency = -1; + userOptions.outputLatency = -1; + userOptions.waveFilePath = "."; + + // Process arguments. Skip name of executable. + i = 1; + while( imaxInputChannels ); printf( ", %2d out", deviceInfo->maxOutputChannels ); - printf( ", %s", deviceInfo->name ); + printf( ", %s", deviceInfo->name ); printf( ", on %s\n", Pa_GetHostApiInfo( deviceInfo->hostApi )->name ); - } + } } /*******************************************************************/ void PaQa_ConvertToFloat( const void *input, int numSamples, PaSampleFormat inFormat, float *output ) { - int i; - switch( inFormat ) - { - case paUInt8: - { - unsigned char *data = (unsigned char *)input; - for( i=0; i> 8; - float fval = (float) (value / ((double) 0x00800000)); - *output++ = fval; - } - } - break; - } - + int i; + switch( inFormat ) + { + case paUInt8: + { + unsigned char *data = (unsigned char *)input; + for( i=0; i> 8; + float fval = (float) (value / ((double) 0x00800000)); + *output++ = fval; + } + } + break; + } + } /*******************************************************************/ void PaQa_ConvertFromFloat( const float *input, int numSamples, PaSampleFormat outFormat, void *output ) { - int i; - switch( outFormat ) - { - case paUInt8: - { - unsigned char *data = (unsigned char *)output; - for( i=0; i(tolerance)) \ - { \ - printf( "%s:%d - ERROR - %s, expected %f, got %f, tol=%f\n", __FILE__, __LINE__, message, ((double)(expected)), ((double)(actual)), ((double)(tolerance)) ); \ - g_testsFailed++; \ - goto error; \ - } \ - else g_testsPassed++; + if (fabs((expected)-(actual))>(tolerance)) \ + { \ + printf( "%s:%d - ERROR - %s, expected %f, got %f, tol=%f\n", __FILE__, __LINE__, message, ((double)(expected)), ((double)(actual)), ((double)(tolerance)) ); \ + g_testsFailed++; \ + goto error; \ + } \ + else g_testsPassed++; #define QA_ASSERT_CLOSE_INT( message, expected, actual, tolerance ) \ if (abs((expected)-(actual))>(tolerance)) \ diff --git a/3rdparty/portaudio/qa/loopback/src/test_audio_analyzer.c b/3rdparty/portaudio/qa/loopback/src/test_audio_analyzer.c index add57d495e2..82fa859f5ea 100644 --- a/3rdparty/portaudio/qa/loopback/src/test_audio_analyzer.c +++ b/3rdparty/portaudio/qa/loopback/src/test_audio_analyzer.c @@ -26,13 +26,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -56,48 +56,48 @@ */ static int TestSingleMonoTone( void ) { - int result = 0; - PaQaSineGenerator generator; - PaQaRecording recording; - float buffer[FRAMES_PER_BLOCK]; - double sampleRate = 44100.0; - int maxFrames = ((int)sampleRate) * 1; - int samplesPerFrame = 1; - int stride = 1; + int result = 0; + PaQaSineGenerator generator; + PaQaRecording recording; + float buffer[FRAMES_PER_BLOCK]; + double sampleRate = 44100.0; + int maxFrames = ((int)sampleRate) * 1; + int samplesPerFrame = 1; + int stride = 1; int done = 0; - double freq = 234.5; - double amp = 0.5; - + double freq = 234.5; + double amp = 0.5; + double mag1, mag2; - // Setup a sine oscillator. - PaQa_SetupSineGenerator( &generator, freq, amp, sampleRate ); - - result = PaQa_InitializeRecording( &recording, maxFrames, (int) sampleRate ); - QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); - - done = 0; - while (!done) - { - PaQa_EraseBuffer( buffer, FRAMES_PER_BLOCK, samplesPerFrame ); - PaQa_MixSine( &generator, buffer, FRAMES_PER_BLOCK, stride ); - done = PaQa_WriteRecording( &recording, buffer, FRAMES_PER_BLOCK, samplesPerFrame ); - } - - mag1 = PaQa_CorrelateSine( &recording, freq, sampleRate, 0, recording.numFrames, NULL ); - QA_ASSERT_CLOSE( "exact frequency match", amp, mag1, 0.01 ); - - mag2 = PaQa_CorrelateSine( &recording, freq * 1.23, sampleRate, 0, recording.numFrames, NULL ); - QA_ASSERT_CLOSE( "wrong frequency", 0.0, mag2, 0.01 ); - - PaQa_TerminateRecording( &recording ); - return 0; - + // Setup a sine oscillator. + PaQa_SetupSineGenerator( &generator, freq, amp, sampleRate ); + + result = PaQa_InitializeRecording( &recording, maxFrames, (int) sampleRate ); + QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); + + done = 0; + while (!done) + { + PaQa_EraseBuffer( buffer, FRAMES_PER_BLOCK, samplesPerFrame ); + PaQa_MixSine( &generator, buffer, FRAMES_PER_BLOCK, stride ); + done = PaQa_WriteRecording( &recording, buffer, FRAMES_PER_BLOCK, samplesPerFrame ); + } + + mag1 = PaQa_CorrelateSine( &recording, freq, sampleRate, 0, recording.numFrames, NULL ); + QA_ASSERT_CLOSE( "exact frequency match", amp, mag1, 0.01 ); + + mag2 = PaQa_CorrelateSine( &recording, freq * 1.23, sampleRate, 0, recording.numFrames, NULL ); + QA_ASSERT_CLOSE( "wrong frequency", 0.0, mag2, 0.01 ); + + PaQa_TerminateRecording( &recording ); + return 0; + error: - PaQa_TerminateRecording( &recording); - return 1; - + PaQa_TerminateRecording( &recording); + return 1; + } /*==========================================================================================*/ @@ -107,60 +107,60 @@ error: static int TestMixedMonoTones( void ) { - int i; - int result = 0; + int i; + int result = 0; #define NUM_TONES (5) - PaQaSineGenerator generators[NUM_TONES]; - PaQaRecording recording; - float buffer[FRAMES_PER_BLOCK]; - double sampleRate = 44100.0; - int maxFrames = ((int)sampleRate) * 1; - int samplesPerFrame = 1; - - double baseFreq = 234.5; - double amp = 0.1; - + PaQaSineGenerator generators[NUM_TONES]; + PaQaRecording recording; + float buffer[FRAMES_PER_BLOCK]; + double sampleRate = 44100.0; + int maxFrames = ((int)sampleRate) * 1; + int samplesPerFrame = 1; + + double baseFreq = 234.5; + double amp = 0.1; + double mag2; int stride = samplesPerFrame; - int done = 0; - - // Setup a sine oscillator. - for( i=0; istartDelay; - - int stride = 1; - // Record some initial silence. - int done = PaQa_WriteSilence( recording, testTone->startDelay ); - + + int stride = 1; + // Record some initial silence. + int done = PaQa_WriteSilence( recording, testTone->startDelay ); + // Setup a sine oscillator. - PaQa_SetupSineGenerator( &generator, testTone->frequency, testTone->amplitude, testTone->sampleRate ); - - while (!done) - { - int framesThisLoop = BUFFER_SIZE; - - if( frameCounter == glitchPosition ) - { - if( framesToAdd > 0 ) - { - // Record some frozen data without advancing the sine generator. - done = PaQa_RecordFreeze( recording, framesToAdd ); - frameCounter += framesToAdd; - } - else if( framesToAdd < 0 ) - { - // Advance sine generator a few frames. - PaQa_MixSine( &generator, buffer, 0 - framesToAdd, stride ); - } - - } - else if( (frameCounter < glitchPosition) && ((frameCounter + framesThisLoop) > glitchPosition) ) - { - // Go right up to the glitchPosition. - framesThisLoop = glitchPosition - frameCounter; - } - - if( framesThisLoop > 0 ) - { - PaQa_EraseBuffer( buffer, framesThisLoop, testTone->samplesPerFrame ); - PaQa_MixSine( &generator, buffer, framesThisLoop, stride ); - done = PaQa_WriteRecording( recording, buffer, framesThisLoop, testTone->samplesPerFrame ); - } - frameCounter += framesThisLoop; - } + PaQa_SetupSineGenerator( &generator, testTone->frequency, testTone->amplitude, testTone->sampleRate ); + + while (!done) + { + int framesThisLoop = BUFFER_SIZE; + + if( frameCounter == glitchPosition ) + { + if( framesToAdd > 0 ) + { + // Record some frozen data without advancing the sine generator. + done = PaQa_RecordFreeze( recording, framesToAdd ); + frameCounter += framesToAdd; + } + else if( framesToAdd < 0 ) + { + // Advance sine generator a few frames. + PaQa_MixSine( &generator, buffer, 0 - framesToAdd, stride ); + } + + } + else if( (frameCounter < glitchPosition) && ((frameCounter + framesThisLoop) > glitchPosition) ) + { + // Go right up to the glitchPosition. + framesThisLoop = glitchPosition - frameCounter; + } + + if( framesThisLoop > 0 ) + { + PaQa_EraseBuffer( buffer, framesThisLoop, testTone->samplesPerFrame ); + PaQa_MixSine( &generator, buffer, framesThisLoop, stride ); + done = PaQa_WriteRecording( recording, buffer, framesThisLoop, testTone->samplesPerFrame ); + } + frameCounter += framesThisLoop; + } } @@ -227,24 +227,24 @@ static void MakeRecordingWithAddedFrames( PaQaRecording *recording, PaQaTestTone static void MakeCleanRecording( PaQaRecording *recording, PaQaTestTone *testTone ) { - PaQaSineGenerator generator; + PaQaSineGenerator generator; #define BUFFER_SIZE 512 - float buffer[BUFFER_SIZE]; - - int stride = 1; - // Record some initial silence. - int done = PaQa_WriteSilence( recording, testTone->startDelay ); - - // Setup a sine oscillator. - PaQa_SetupSineGenerator( &generator, testTone->frequency, testTone->amplitude, testTone->sampleRate ); - - // Generate recording with good phase. - while (!done) - { - PaQa_EraseBuffer( buffer, BUFFER_SIZE, testTone->samplesPerFrame ); - PaQa_MixSine( &generator, buffer, BUFFER_SIZE, stride ); - done = PaQa_WriteRecording( recording, buffer, BUFFER_SIZE, testTone->samplesPerFrame ); - } + float buffer[BUFFER_SIZE]; + + int stride = 1; + // Record some initial silence. + int done = PaQa_WriteSilence( recording, testTone->startDelay ); + + // Setup a sine oscillator. + PaQa_SetupSineGenerator( &generator, testTone->frequency, testTone->amplitude, testTone->sampleRate ); + + // Generate recording with good phase. + while (!done) + { + PaQa_EraseBuffer( buffer, BUFFER_SIZE, testTone->samplesPerFrame ); + PaQa_MixSine( &generator, buffer, BUFFER_SIZE, stride ); + done = PaQa_WriteRecording( recording, buffer, BUFFER_SIZE, testTone->samplesPerFrame ); + } } /*==========================================================================================*/ @@ -254,22 +254,22 @@ static void MakeCleanRecording( PaQaRecording *recording, PaQaTestTone *testTone static void MakeRecordingWithPop( PaQaRecording *recording, PaQaTestTone *testTone, int popPosition, int popWidth, double popAmplitude ) { - int i; - - MakeCleanRecording( recording, testTone ); - - // Apply glitch to good recording. - if( (popPosition + popWidth) >= recording->numFrames ) - { - popWidth = (recording->numFrames - popPosition) - 1; - } - - for( i=0; ibuffer[i+popPosition]; - float bad = (good > 0.0) ? (good - popAmplitude) : (good + popAmplitude); - recording->buffer[i+popPosition] = bad; - } + int i; + + MakeCleanRecording( recording, testTone ); + + // Apply glitch to good recording. + if( (popPosition + popWidth) >= recording->numFrames ) + { + popWidth = (recording->numFrames - popPosition) - 1; + } + + for( i=0; ibuffer[i+popPosition]; + float bad = (good > 0.0) ? (good - popAmplitude) : (good + popAmplitude); + recording->buffer[i+popPosition] = bad; + } } /*==========================================================================================*/ @@ -278,54 +278,54 @@ static void MakeRecordingWithPop( PaQaRecording *recording, PaQaTestTone *testTo */ static int TestDetectSinglePhaseError( double sampleRate, int cycleSize, int latencyFrames, int glitchPosition, int framesAdded ) { - int result = 0; - PaQaRecording recording; - PaQaTestTone testTone; - PaQaAnalysisResult analysisResult = { 0.0 }; - int framesDropped = 0; + int result = 0; + PaQaRecording recording; + PaQaTestTone testTone; + PaQaAnalysisResult analysisResult = { 0.0 }; + int framesDropped = 0; int maxFrames = ((int)sampleRate) * 2; - testTone.samplesPerFrame = 1; - testTone.sampleRate = sampleRate; - testTone.frequency = sampleRate / cycleSize; - testTone.amplitude = 0.5; - testTone.startDelay = latencyFrames; - - result = PaQa_InitializeRecording( &recording, maxFrames, (int) sampleRate ); - QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); - - MakeRecordingWithAddedFrames( &recording, &testTone, glitchPosition, framesAdded ); - - PaQa_AnalyseRecording( &recording, &testTone, &analysisResult ); - - if( framesAdded < 0 ) - { - framesDropped = -framesAdded; - framesAdded = 0; - } - + testTone.samplesPerFrame = 1; + testTone.sampleRate = sampleRate; + testTone.frequency = sampleRate / cycleSize; + testTone.amplitude = 0.5; + testTone.startDelay = latencyFrames; + + result = PaQa_InitializeRecording( &recording, maxFrames, (int) sampleRate ); + QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); + + MakeRecordingWithAddedFrames( &recording, &testTone, glitchPosition, framesAdded ); + + PaQa_AnalyseRecording( &recording, &testTone, &analysisResult ); + + if( framesAdded < 0 ) + { + framesDropped = -framesAdded; + framesAdded = 0; + } + #if PRINT_REPORTS - printf("\n=== Dropped Frame Analysis ===================\n"); - printf(" expected actual\n"); - printf(" latency: %10.3f %10.3f\n", (double)latencyFrames, analysisResult.latency ); - printf(" num added frames: %10.3f %10.3f\n", (double)framesAdded, analysisResult.numAddedFrames ); - printf(" added frames at: %10.3f %10.3f\n", (double)glitchPosition, analysisResult.addedFramesPosition ); - printf(" num dropped frames: %10.3f %10.3f\n", (double)framesDropped, analysisResult.numDroppedFrames ); - printf(" dropped frames at: %10.3f %10.3f\n", (double)glitchPosition, analysisResult.droppedFramesPosition ); + printf("\n=== Dropped Frame Analysis ===================\n"); + printf(" expected actual\n"); + printf(" latency: %10.3f %10.3f\n", (double)latencyFrames, analysisResult.latency ); + printf(" num added frames: %10.3f %10.3f\n", (double)framesAdded, analysisResult.numAddedFrames ); + printf(" added frames at: %10.3f %10.3f\n", (double)glitchPosition, analysisResult.addedFramesPosition ); + printf(" num dropped frames: %10.3f %10.3f\n", (double)framesDropped, analysisResult.numDroppedFrames ); + printf(" dropped frames at: %10.3f %10.3f\n", (double)glitchPosition, analysisResult.droppedFramesPosition ); #endif - - QA_ASSERT_CLOSE( "PaQa_AnalyseRecording latency", latencyFrames, analysisResult.latency, 0.5 ); - QA_ASSERT_CLOSE( "PaQa_AnalyseRecording framesAdded", framesAdded, analysisResult.numAddedFrames, 1.0 ); - QA_ASSERT_CLOSE( "PaQa_AnalyseRecording framesDropped", framesDropped, analysisResult.numDroppedFrames, 1.0 ); -// QA_ASSERT_CLOSE( "PaQa_AnalyseRecording glitchPosition", glitchPosition, analysisResult.glitchPosition, cycleSize ); - - PaQa_TerminateRecording( &recording ); - return 0; - + + QA_ASSERT_CLOSE( "PaQa_AnalyseRecording latency", latencyFrames, analysisResult.latency, 0.5 ); + QA_ASSERT_CLOSE( "PaQa_AnalyseRecording framesAdded", framesAdded, analysisResult.numAddedFrames, 1.0 ); + QA_ASSERT_CLOSE( "PaQa_AnalyseRecording framesDropped", framesDropped, analysisResult.numDroppedFrames, 1.0 ); +// QA_ASSERT_CLOSE( "PaQa_AnalyseRecording glitchPosition", glitchPosition, analysisResult.glitchPosition, cycleSize ); + + PaQa_TerminateRecording( &recording ); + return 0; + error: - PaQa_TerminateRecording( &recording); - return 1; -} + PaQa_TerminateRecording( &recording); + return 1; +} /*==========================================================================================*/ /** @@ -333,34 +333,34 @@ error: */ static int TestDetectPhaseErrors( void ) { - int result; - - result = TestDetectSinglePhaseError( 44100, 200, 477, -1, 0 ); - if( result < 0 ) return result; + int result; + + result = TestDetectSinglePhaseError( 44100, 200, 477, -1, 0 ); + if( result < 0 ) return result; /* - result = TestDetectSinglePhaseError( 44100, 200, 77, -1, 0 ); - if( result < 0 ) return result; - - result = TestDetectSinglePhaseError( 44100, 200, 83, 3712, 9 ); - if( result < 0 ) return result; - - result = TestDetectSinglePhaseError( 44100, 280, 83, 3712, 27 ); - if( result < 0 ) return result; - - result = TestDetectSinglePhaseError( 44100, 200, 234, 3712, -9 ); - if( result < 0 ) return result; - - result = TestDetectSinglePhaseError( 44100, 200, 2091, 8923, -2 ); - if( result < 0 ) return result; - - result = TestDetectSinglePhaseError( 44100, 120, 1782, 5772, -18 ); - if( result < 0 ) return result; - - // Note that if the frequency is too high then it is hard to detect single dropped frames. - result = TestDetectSinglePhaseError( 44100, 200, 500, 4251, -1 ); - if( result < 0 ) return result; + result = TestDetectSinglePhaseError( 44100, 200, 77, -1, 0 ); + if( result < 0 ) return result; + + result = TestDetectSinglePhaseError( 44100, 200, 83, 3712, 9 ); + if( result < 0 ) return result; + + result = TestDetectSinglePhaseError( 44100, 280, 83, 3712, 27 ); + if( result < 0 ) return result; + + result = TestDetectSinglePhaseError( 44100, 200, 234, 3712, -9 ); + if( result < 0 ) return result; + + result = TestDetectSinglePhaseError( 44100, 200, 2091, 8923, -2 ); + if( result < 0 ) return result; + + result = TestDetectSinglePhaseError( 44100, 120, 1782, 5772, -18 ); + if( result < 0 ) return result; + + // Note that if the frequency is too high then it is hard to detect single dropped frames. + result = TestDetectSinglePhaseError( 44100, 200, 500, 4251, -1 ); + if( result < 0 ) return result; */ - return 0; + return 0; } /*==========================================================================================*/ @@ -369,53 +369,53 @@ static int TestDetectPhaseErrors( void ) */ static int TestDetectSinglePop( double sampleRate, int cycleSize, int latencyFrames, int popPosition, int popWidth, double popAmplitude ) { - int result = 0; - PaQaRecording recording; - PaQaTestTone testTone; - PaQaAnalysisResult analysisResult = { 0.0 }; - int maxFrames = ((int)sampleRate) * 2; - - testTone.samplesPerFrame = 1; - testTone.sampleRate = sampleRate; - testTone.frequency = sampleRate / cycleSize; - testTone.amplitude = 0.5; - testTone.startDelay = latencyFrames; - - result = PaQa_InitializeRecording( &recording, maxFrames, (int) sampleRate ); - QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); - - MakeRecordingWithPop( &recording, &testTone, popPosition, popWidth, popAmplitude ); - - PaQa_AnalyseRecording( &recording, &testTone, &analysisResult ); - + int result = 0; + PaQaRecording recording; + PaQaTestTone testTone; + PaQaAnalysisResult analysisResult = { 0.0 }; + int maxFrames = ((int)sampleRate) * 2; + + testTone.samplesPerFrame = 1; + testTone.sampleRate = sampleRate; + testTone.frequency = sampleRate / cycleSize; + testTone.amplitude = 0.5; + testTone.startDelay = latencyFrames; + + result = PaQa_InitializeRecording( &recording, maxFrames, (int) sampleRate ); + QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); + + MakeRecordingWithPop( &recording, &testTone, popPosition, popWidth, popAmplitude ); + + PaQa_AnalyseRecording( &recording, &testTone, &analysisResult ); + #if PRINT_REPORTS - printf("\n=== Pop Analysis ===================\n"); - printf(" expected actual\n"); - printf(" latency: %10.3f %10.3f\n", (double)latencyFrames, analysisResult.latency ); - printf(" popPosition: %10.3f %10.3f\n", (double)popPosition, analysisResult.popPosition ); - printf(" popAmplitude: %10.3f %10.3f\n", popAmplitude, analysisResult.popAmplitude ); - printf(" cycleSize: %6d\n", cycleSize ); - printf(" num added frames: %10.3f\n", analysisResult.numAddedFrames ); - printf(" added frames at: %10.3f\n", analysisResult.addedFramesPosition ); - printf(" num dropped frames: %10.3f\n", analysisResult.numDroppedFrames ); - printf(" dropped frames at: %10.3f\n", analysisResult.droppedFramesPosition ); + printf("\n=== Pop Analysis ===================\n"); + printf(" expected actual\n"); + printf(" latency: %10.3f %10.3f\n", (double)latencyFrames, analysisResult.latency ); + printf(" popPosition: %10.3f %10.3f\n", (double)popPosition, analysisResult.popPosition ); + printf(" popAmplitude: %10.3f %10.3f\n", popAmplitude, analysisResult.popAmplitude ); + printf(" cycleSize: %6d\n", cycleSize ); + printf(" num added frames: %10.3f\n", analysisResult.numAddedFrames ); + printf(" added frames at: %10.3f\n", analysisResult.addedFramesPosition ); + printf(" num dropped frames: %10.3f\n", analysisResult.numDroppedFrames ); + printf(" dropped frames at: %10.3f\n", analysisResult.droppedFramesPosition ); #endif - - QA_ASSERT_CLOSE( "PaQa_AnalyseRecording latency", latencyFrames, analysisResult.latency, 0.5 ); - QA_ASSERT_CLOSE( "PaQa_AnalyseRecording popPosition", popPosition, analysisResult.popPosition, 10 ); - if( popWidth > 0 ) - { - QA_ASSERT_CLOSE( "PaQa_AnalyseRecording popAmplitude", popAmplitude, analysisResult.popAmplitude, 0.1 * popAmplitude ); - } - - PaQa_TerminateRecording( &recording ); - return 0; - + + QA_ASSERT_CLOSE( "PaQa_AnalyseRecording latency", latencyFrames, analysisResult.latency, 0.5 ); + QA_ASSERT_CLOSE( "PaQa_AnalyseRecording popPosition", popPosition, analysisResult.popPosition, 10 ); + if( popWidth > 0 ) + { + QA_ASSERT_CLOSE( "PaQa_AnalyseRecording popAmplitude", popAmplitude, analysisResult.popAmplitude, 0.1 * popAmplitude ); + } + + PaQa_TerminateRecording( &recording ); + return 0; + error: - PaQa_SaveRecordingToWaveFile( &recording, "bad_recording.wav" ); - PaQa_TerminateRecording( &recording); - return 1; -} + PaQa_SaveRecordingToWaveFile( &recording, "bad_recording.wav" ); + PaQa_TerminateRecording( &recording); + return 1; +} /*==========================================================================================*/ /** @@ -423,73 +423,73 @@ error: */ static int TestSingleInitialSpike( double sampleRate, int stepPosition, int cycleSize, int latencyFrames, double stepAmplitude ) { - int i; - int result = 0; - // Account for highpass filter offset. - int expectedLatency = latencyFrames + 1; - PaQaRecording recording; - - PaQaRecording hipassOutput = { 0 }; - BiquadFilter hipassFilter; - - PaQaTestTone testTone; - PaQaAnalysisResult analysisResult = { 0.0 }; - int maxFrames = ((int)sampleRate) * 2; - - testTone.samplesPerFrame = 1; - testTone.sampleRate = sampleRate; - testTone.frequency = sampleRate / cycleSize; - testTone.amplitude = -0.5; - testTone.startDelay = latencyFrames; - - result = PaQa_InitializeRecording( &recording, maxFrames, (int) sampleRate ); - QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); - - result = PaQa_InitializeRecording( &hipassOutput, maxFrames, (int) sampleRate ); - QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); - - MakeCleanRecording( &recording, &testTone ); - - // Apply DC step. - for( i=stepPosition; i>8); - *addr++ = (unsigned char) (data>>16); - *addr++ = (unsigned char) (data>>24); - *addrPtr = addr; + unsigned char *addr = *addrPtr; + *addr++ = (unsigned char) data; + *addr++ = (unsigned char) (data>>8); + *addr++ = (unsigned char) (data>>16); + *addr++ = (unsigned char) (data>>24); + *addrPtr = addr; } /* Write short word data to a little endian format byte array. */ static void WriteShortLE( unsigned char **addrPtr, unsigned short data ) { - unsigned char *addr = *addrPtr; - *addr++ = (unsigned char) data; - *addr++ = (unsigned char) (data>>8); - *addrPtr = addr; + unsigned char *addr = *addrPtr; + *addr++ = (unsigned char) data; + *addr++ = (unsigned char) (data>>8); + *addrPtr = addr; } /* Write IFF ChunkType data to a byte array. */ static void WriteChunkType( unsigned char **addrPtr, unsigned long cktyp ) { - unsigned char *addr = *addrPtr; - *addr++ = (unsigned char) (cktyp>>24); - *addr++ = (unsigned char) (cktyp>>16); - *addr++ = (unsigned char) (cktyp>>8); - *addr++ = (unsigned char) cktyp; - *addrPtr = addr; + unsigned char *addr = *addrPtr; + *addr++ = (unsigned char) (cktyp>>24); + *addr++ = (unsigned char) (cktyp>>16); + *addr++ = (unsigned char) (cktyp>>8); + *addr++ = (unsigned char) cktyp; + *addrPtr = addr; } #define WAV_HEADER_SIZE (4 + 4 + 4 + /* RIFF+size+WAVE */ \ @@ -87,14 +87,14 @@ static void WriteChunkType( unsigned char **addrPtr, unsigned long cktyp ) */ long Audio_WAV_OpenWriter( WAV_Writer *writer, const char *fileName, int frameRate, int samplesPerFrame ) { - unsigned int bytesPerSecond; + unsigned int bytesPerSecond; unsigned char header[ WAV_HEADER_SIZE ]; - unsigned char *addr = header; + unsigned char *addr = header; int numWritten; - + writer->dataSize = 0; writer->dataSizeOffset = 0; - + writer->fid = fopen( fileName, "wb" ); if( writer->fid == NULL ) { @@ -102,35 +102,35 @@ long Audio_WAV_OpenWriter( WAV_Writer *writer, const char *fileName, int frameRa } /* Write RIFF header. */ - WriteChunkType( &addr, RIFF_ID ); + WriteChunkType( &addr, RIFF_ID ); /* Write RIFF size as zero for now. Will patch later. */ - WriteLongLE( &addr, 0 ); + WriteLongLE( &addr, 0 ); /* Write WAVE form ID. */ - WriteChunkType( &addr, WAVE_ID ); + WriteChunkType( &addr, WAVE_ID ); /* Write format chunk based on AudioSample structure. */ - WriteChunkType( &addr, FMT_ID ); + WriteChunkType( &addr, FMT_ID ); WriteLongLE( &addr, 16 ); WriteShortLE( &addr, WAVE_FORMAT_PCM ); - bytesPerSecond = frameRate * samplesPerFrame * sizeof( short); - WriteShortLE( &addr, (short) samplesPerFrame ); - WriteLongLE( &addr, frameRate ); - WriteLongLE( &addr, bytesPerSecond ); - WriteShortLE( &addr, (short) (samplesPerFrame * sizeof( short)) ); /* bytesPerBlock */ - WriteShortLE( &addr, (short) 16 ); /* bits per sample */ + bytesPerSecond = frameRate * samplesPerFrame * sizeof( short); + WriteShortLE( &addr, (short) samplesPerFrame ); + WriteLongLE( &addr, frameRate ); + WriteLongLE( &addr, bytesPerSecond ); + WriteShortLE( &addr, (short) (samplesPerFrame * sizeof( short)) ); /* bytesPerBlock */ + WriteShortLE( &addr, (short) 16 ); /* bits per sample */ /* Write ID and size for 'data' chunk. */ - WriteChunkType( &addr, DATA_ID ); + WriteChunkType( &addr, DATA_ID ); /* Save offset so we can patch it later. */ writer->dataSizeOffset = (int) (addr - header); - WriteLongLE( &addr, 0 ); + WriteLongLE( &addr, 0 ); numWritten = fwrite( header, 1, sizeof(header), writer->fid ); if( numWritten != sizeof(header) ) return -1; - return (int) numWritten; + return (int) numWritten; } /********************************************************************************* @@ -138,31 +138,31 @@ long Audio_WAV_OpenWriter( WAV_Writer *writer, const char *fileName, int frameRa * Returns bytes written or negative error code. */ long Audio_WAV_WriteShorts( WAV_Writer *writer, - short *samples, - int numSamples - ) + short *samples, + int numSamples + ) { - unsigned char buffer[2]; + unsigned char buffer[2]; unsigned char *bufferPtr; - int i; - short *p = samples; + int i; + short *p = samples; int numWritten; int bytesWritten; - if( numSamples <= 0 ) - { - return -1; - } + if( numSamples <= 0 ) + { + return -1; + } for( i=0; ifid ); if( numWritten != sizeof(buffer) ) return -1; - } + } bytesWritten = numSamples * sizeof(short); writer->dataSize += bytesWritten; - return (int) bytesWritten; + return (int) bytesWritten; } /********************************************************************************* @@ -171,7 +171,7 @@ long Audio_WAV_WriteShorts( WAV_Writer *writer, */ long Audio_WAV_CloseWriter( WAV_Writer *writer ) { - unsigned char buffer[4]; + unsigned char buffer[4]; unsigned char *bufferPtr; int numWritten; int riffSize; @@ -212,7 +212,7 @@ int main( void ) #define NUM_SAMPLES (200) short data[NUM_SAMPLES]; short saw = 0; - + for( i=0; i +#include +#include +#define _USE_MATH_DEFINES #include #include "portaudio.h" #include "pa_trace.h" /****************************************** Definitions ***********/ -#define MODE_INPUT (0) -#define MODE_OUTPUT (1) -#define MAX_TEST_CHANNELS 4 +#define MODE_INPUT (0) +#define MODE_OUTPUT (1) +#define MAX_TEST_CHANNELS (4) +#define LOWEST_FREQUENCY (300.0) +#define LOWEST_SAMPLE_RATE (8000.0) +#define PHASE_INCREMENT (2.0 * M_PI * LOWEST_FREQUENCY / LOWEST_SAMPLE_RATE) +#define SINE_AMPLITUDE (0.2) typedef struct PaQaData { @@ -67,13 +75,13 @@ typedef struct PaQaData int numChannels; int bytesPerSample; int mode; - short sawPhase; + float phase; PaSampleFormat format; } PaQaData; /****************************************** Prototypes ***********/ -static void TestDevices( int mode ); +static void TestDevices( int mode, int allDevices ); static void TestFormats( int mode, PaDeviceIndex deviceID, double sampleRate, int numChannels ); static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate, @@ -100,13 +108,21 @@ static int gNumFailed = 0; } \ else { \ printf("ERROR - 0x%x - %s for %s\n", result, \ - ((result == 0) ? "-" : Pa_GetErrorText(result)), \ - #_exp ); \ + ((result == 0) ? "-" : Pa_GetErrorText(result)), \ + #_exp ); \ gNumFailed++; \ goto error; \ } \ } while(0) +static float NextSineSample( PaQaData *data ) +{ + float phase = data->phase + PHASE_INCREMENT; + if( phase > M_PI ) phase -= (float) (2.0 * M_PI); + data->phase = phase; + return sinf(phase) * SINE_AMPLITUDE; +} + /*******************************************************************/ /* This routine will be called by the PortAudio engine when audio is needed. ** It may be called at interrupt level on some machines so don't do anything @@ -118,27 +134,26 @@ static int QaCallback( const void *inputBuffer, void *outputBuffer, PaStreamCallbackFlags statusFlags, void *userData ) { - unsigned long i; - short phase; + unsigned long frameIndex; + unsigned long channelIndex; + float sample; PaQaData *data = (PaQaData *) userData; (void) inputBuffer; - /* Play simple sawtooth wave. */ + /* Play simple sine wave. */ if( data->mode == MODE_OUTPUT ) { - phase = data->sawPhase; switch( data->format ) { case paFloat32: { float *out = (float *) outputBuffer; - for( i=0; inumChannels == 2 ) + sample = NextSineSample( data ); + for( channelIndex = 0; channelIndex < data->numChannels; channelIndex++ ) { - *out++ = (float) (phase * (1.0 / 32768.0)); + *out++ = sample; } } } @@ -147,28 +162,26 @@ static int QaCallback( const void *inputBuffer, void *outputBuffer, case paInt32: { int *out = (int *) outputBuffer; - for( i=0; inumChannels == 2 ) + sample = NextSineSample( data ); + for( channelIndex = 0; channelIndex < data->numChannels; channelIndex++ ) { - *out++ = ((int) phase ) << 16; + *out++ = ((int)(sample * 0x00800000)) << 8; } } } break; - + case paInt16: { short *out = (short *) outputBuffer; - for( i=0; inumChannels == 2 ) + sample = NextSineSample( data ); + for( channelIndex = 0; channelIndex < data->numChannels; channelIndex++ ) { - *out++ = phase; + *out++ = (short)(sample * 32767); } } } @@ -178,14 +191,10 @@ static int QaCallback( const void *inputBuffer, void *outputBuffer, { unsigned char *out = (unsigned char *) outputBuffer; unsigned long numBytes = framesPerBuffer * data->numChannels * data->bytesPerSample; - for( i=0; isawPhase = phase; } /* Are we through yet? */ if( data->framesLeft > framesPerBuffer ) @@ -203,15 +212,78 @@ static int QaCallback( const void *inputBuffer, void *outputBuffer, } /*******************************************************************/ -int main(void); -int main(void) +static void usage( const char *name ) +{ + printf("%s [-a]\n", name); + printf(" -a - Test ALL devices, otherwise just the default devices.\n"); + printf(" -i - Test INPUT only.\n"); + printf(" -o - Test OUTPUT only.\n"); + printf(" -? - Help\n"); +} + +/*******************************************************************/ +int main( int argc, char **argv ); +int main( int argc, char **argv ) { + int i; PaError result; + int allDevices = 0; + int testOutput = 1; + int testInput = 1; + char *executableName = argv[0]; + + /* Parse command line parameters. */ + i = 1; + while( imaxInputChannels : pdi->maxOutputChannels); + + if( mode == MODE_INPUT ) { + maxChannels = pdi->maxInputChannels; + isDefault = ( id == Pa_GetDefaultInputDevice()); + } else { + maxChannels = pdi->maxOutputChannels; + isDefault = ( id == Pa_GetDefaultOutputDevice()); + } if( maxChannels > MAX_TEST_CHANNELS ) maxChannels = MAX_TEST_CHANNELS; - + + if (!allDevices && !isDefault) continue; // skip this device + for( jc=1; jc<=maxChannels; jc++ ) { - printf("\n========================================================================\n"); + printf("\n===========================================================\n"); printf(" Device = %s\n", pdi->name ); - printf("========================================================================\n"); + printf("===========================================================\n"); /* Try each standard sample rate. */ for( i=0; standardSampleRates[i] > 0; i++ ) { @@ -273,7 +354,7 @@ static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate, PaQaData myData; #define FRAMES_PER_BUFFER (64) const int kNumSeconds = 100; - + /* Setup data for synthesis thread. */ myData.framesLeft = (unsigned long) (sampleRate * kNumSeconds); myData.numChannels = numChannels; @@ -299,32 +380,35 @@ static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate, inputParameters.device = deviceID; inputParameters.channelCount = numChannels; inputParameters.sampleFormat = format; - inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency; + inputParameters.suggestedLatency = + Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency; inputParameters.hostApiSpecificStreamInfo = NULL; ipp = &inputParameters; } else { - ipp = NULL; - } - + ipp = NULL; + } + if( mode == MODE_OUTPUT ) { outputParameters.device = deviceID; outputParameters.channelCount = numChannels; outputParameters.sampleFormat = format; - outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; + outputParameters.suggestedLatency = + Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; opp = &outputParameters; } else { - opp = NULL; - } - + opp = NULL; + } + if(paFormatIsSupported == Pa_IsFormatSupported( ipp, opp, sampleRate )) { - printf("------ TestAdvance: %s, device = %d, rate = %g, numChannels = %d, format = %lu -------\n", + printf("------ TestAdvance: %s, device = %d, rate = %g" + ", numChannels = %d, format = %lu -------\n", ( mode == MODE_INPUT ) ? "INPUT" : "OUTPUT", deviceID, sampleRate, numChannels, (unsigned long)format); EXPECT( ((result = Pa_OpenStream( &stream, @@ -353,7 +437,7 @@ static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate, oldStamp = Pa_GetStreamTime(stream); Pa_Sleep(msec); newStamp = Pa_GetStreamTime(stream); - printf("oldStamp = %9.6f, newStamp = %9.6f\n", oldStamp, newStamp ); /**/ + printf("oldStamp = %9.6f, newStamp = %9.6f\n", oldStamp, newStamp ); /**/ EXPECT( (oldStamp < newStamp) ); /* Check to make sure callback is decrementing framesLeft. */ oldFrames = myData.framesLeft; diff --git a/3rdparty/portaudio/qa/paqa_errs.c b/3rdparty/portaudio/qa/paqa_errs.c index 8c1d06d96ed..8d4094f94c3 100644 --- a/3rdparty/portaudio/qa/paqa_errs.c +++ b/3rdparty/portaudio/qa/paqa_errs.c @@ -1,8 +1,8 @@ /** @file paqa_errs.c - @ingroup qa_src - @brief Self Testing Quality Assurance app for PortAudio - Do lots of bad things to test error reporting. - @author Phil Burk http://www.softsynth.com + @ingroup qa_src + @brief Self Testing Quality Assurance app for PortAudio + Do lots of bad things to test error reporting. + @author Phil Burk http://www.softsynth.com Pieter Suurmond adapted to V19 API. */ /* @@ -33,16 +33,16 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ - + #include #include @@ -103,14 +103,14 @@ static int gNumFailed = 0; static int QaCallback( const void* inputBuffer, void* outputBuffer, unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo* timeInfo, - PaStreamCallbackFlags statusFlags, + const PaStreamCallbackTimeInfo* timeInfo, + PaStreamCallbackFlags statusFlags, void* userData ) { unsigned long i; unsigned char* out = (unsigned char *) outputBuffer; PaQaData* data = (PaQaData *) userData; - + (void)inputBuffer; /* Prevent "unused variable" warnings. */ /* Zero out buffer so we don't hear terrible noise. */ @@ -174,7 +174,7 @@ static int TestBadOpens( void ) PaStreamParameters ipp, opp; const PaDeviceInfo* info = NULL; - + /* Setup data for synthesis thread. */ myData.framesLeft = (unsigned long) (SAMPLE_RATE * 100); /* 100 seconds */ myData.numChannels = 1; @@ -222,7 +222,7 @@ static int TestBadOpens( void ) ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 0; ipp.device = Pa_GetDefaultInputDevice(); - opp.channelCount = 0; opp.device = paNoDevice; /* And no output device, and no output channels. */ + opp.channelCount = 0; opp.device = paNoDevice; /* And no output device, and no output channels. */ HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, QaCallback, &myData )) == paInvalidChannelCount)); @@ -274,7 +274,7 @@ static int TestBadOpens( void ) HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp, 1.0, FRAMES_PER_BUFFER, /* 1 cycle per second (1 Hz) is too low. */ paClipOff, QaCallback, &myData )) == paInvalidSampleRate)); - + /*----------------------------- High sample rate: */ ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; @@ -286,7 +286,7 @@ static int TestBadOpens( void ) /*----------------------------- NULL callback: */ /* NULL callback is valid in V19 -- it means use blocking read/write stream - + ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL; ipp.sampleFormat = opp.sampleFormat = paFloat32; ipp.channelCount = 0; ipp.device = paNoDevice; @@ -366,7 +366,7 @@ static int TestBadActions( void ) SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, QaCallback, &myData )) == paNoError)); } - + HOPEFOR(((deviceInfo = Pa_GetDeviceInfo(paNoDevice)) == NULL)); HOPEFOR(((deviceInfo = Pa_GetDeviceInfo(87654)) == NULL)); HOPEFOR(((result = Pa_StartStream(NULL)) == paBadStreamPtr)); @@ -392,7 +392,7 @@ int main(void); int main(void) { PaError result; - + EXPECT(((result = Pa_Initialize()) == paNoError)); TestBadOpens(); TestBadActions(); diff --git a/3rdparty/portaudio/qa/paqa_latency.c b/3rdparty/portaudio/qa/paqa_latency.c index 389c065687b..a70807b5119 100644 --- a/3rdparty/portaudio/qa/paqa_latency.c +++ b/3rdparty/portaudio/qa/paqa_latency.c @@ -1,7 +1,7 @@ /** @file paqa_latency.c - @ingroup qa_src - @brief Test latency estimates. - @author Ross Bencina + @ingroup qa_src + @brief Test latency estimates. + @author Ross Bencina @author Phil Burk */ /* @@ -32,13 +32,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ #include @@ -91,7 +91,7 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer, (void) timeInfo; /* Prevent unused variable warnings. */ (void) statusFlags; (void) inputBuffer; - + if( data->minFramesPerBuffer > framesPerBuffer ) { data->minFramesPerBuffer = framesPerBuffer; @@ -100,7 +100,7 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer, { data->maxFramesPerBuffer = framesPerBuffer; } - + /* Measure min and max output time stamp delta. */ if( data->callbackCount > 0 ) { @@ -115,7 +115,7 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer, } } data->previousTimeInfo = *timeInfo; - + for( i=0; isine[data->left_phase]; /* left */ @@ -125,12 +125,12 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer, data->right_phase += 3; /* higher pitch so we can distinguish left and right. */ if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE; } - + data->callbackCount += 1; return paContinue; } -PaError paqaCheckLatency( PaStreamParameters *outputParamsPtr, +PaError paqaCheckLatency( PaStreamParameters *outputParamsPtr, paTestData *dataPtr, double sampleRate, unsigned long framesPerBuffer ) { PaError err; @@ -142,7 +142,7 @@ PaError paqaCheckLatency( PaStreamParameters *outputParamsPtr, dataPtr->minDeltaDacTime = 9999999.0; dataPtr->maxDeltaDacTime = 0.0; dataPtr->callbackCount = 0; - + printf("Stream parameter: suggestedOutputLatency = %g\n", outputParamsPtr->suggestedLatency ); if( framesPerBuffer == paFramesPerBufferUnspecified ){ printf("Stream parameter: user framesPerBuffer = paFramesPerBufferUnspecified\n" ); @@ -159,7 +159,7 @@ PaError paqaCheckLatency( PaStreamParameters *outputParamsPtr, patestCallback, dataPtr ); if( err != paNoError ) goto error1; - + streamInfo = Pa_GetStreamInfo( stream ); printf("Stream info: inputLatency = %g\n", streamInfo->inputLatency ); printf("Stream info: outputLatency = %g\n", streamInfo->outputLatency ); @@ -169,7 +169,7 @@ PaError paqaCheckLatency( PaStreamParameters *outputParamsPtr, printf("Play for %d seconds.\n", NUM_SECONDS ); Pa_Sleep( NUM_SECONDS * 1000 ); - + printf(" minFramesPerBuffer = %4d\n", dataPtr->minFramesPerBuffer ); printf(" maxFramesPerBuffer = %4d\n", dataPtr->maxFramesPerBuffer ); printf(" minDeltaDacTime = %f\n", dataPtr->minDeltaDacTime ); @@ -181,7 +181,7 @@ PaError paqaCheckLatency( PaStreamParameters *outputParamsPtr, err = Pa_CloseStream( stream ); Pa_Sleep( 1 * 1000 ); - + printf("-------------------------------------\n"); return err; error2: @@ -245,26 +245,26 @@ static int paqaCheckMultipleSuggested( PaDeviceIndex deviceIndex, int isInput ) streamParameters.hostApiSpecificStreamInfo = NULL; streamParameters.sampleFormat = paFloat32; sampleRate = pdi->defaultSampleRate; - + printf(" lowLatency = %g\n", lowLatency ); printf(" highLatency = %g\n", highLatency ); printf(" numChannels = %d\n", numChannels ); printf(" sampleRate = %g\n", sampleRate ); - + if( (highLatency - lowLatency) < 0.001 ) { numLoops = 1; } for( i=0; iinputLatency; @@ -317,7 +317,7 @@ static int paqaVerifySuggestedLatency( void ) int result = 0; const PaDeviceInfo *pdi; int numDevices = Pa_GetDeviceCount(); - + printf("\n ------------------------ paqaVerifySuggestedLatency\n"); for( id=0; iddefaultLowOutputLatency; err = paqaCheckLatency( &outputParameters, &data, sampleRate, framesPerBuffer ); if( err != paNoError ) goto error; - + printf("------------- 64 frame buffer with 1.1 * defaultLow latency.\n"); framesPerBuffer = 64; outputParameters.suggestedLatency = deviceInfo->defaultLowOutputLatency * 1.1; err = paqaCheckLatency( &outputParameters, &data, sampleRate, framesPerBuffer ); if( err != paNoError ) goto error; - + // Try to create a huge buffer that is bigger than the allowed device maximum. printf("------------- Try a huge buffer.\n"); framesPerBuffer = 16*1024; outputParameters.suggestedLatency = ((double)framesPerBuffer) / sampleRate; // approximate err = paqaCheckLatency( &outputParameters, &data, sampleRate, framesPerBuffer ); if( err != paNoError ) goto error; - + printf("------------- Try suggestedLatency = 0.0\n"); outputParameters.suggestedLatency = 0.0; err = paqaCheckLatency( &outputParameters, &data, sampleRate, paFramesPerBufferUnspecified ); if( err != paNoError ) goto error; - + printf("------------- Try suggestedLatency = defaultLowOutputLatency\n"); outputParameters.suggestedLatency = deviceInfo->defaultLowOutputLatency; err = paqaCheckLatency( &outputParameters, &data, sampleRate, paFramesPerBufferUnspecified ); if( err != paNoError ) goto error; - + printf("------------- Try suggestedLatency = defaultHighOutputLatency\n"); outputParameters.suggestedLatency = deviceInfo->defaultHighOutputLatency; err = paqaCheckLatency( &outputParameters, &data, sampleRate, paFramesPerBufferUnspecified ); if( err != paNoError ) goto error; - + printf("------------- Try suggestedLatency = defaultHighOutputLatency * 4\n"); outputParameters.suggestedLatency = deviceInfo->defaultHighOutputLatency * 4; err = paqaCheckLatency( &outputParameters, &data, sampleRate, paFramesPerBufferUnspecified ); if( err != paNoError ) goto error; - + Pa_Terminate(); printf("SUCCESS - test finished.\n"); return err; - + error: Pa_Terminate(); fprintf( stderr, "ERROR - test failed.\n" ); diff --git a/3rdparty/portaudio/src/common/pa_allocation.c b/3rdparty/portaudio/src/common/pa_allocation.c index 51fe15aba8c..f77712ba6de 100644 --- a/3rdparty/portaudio/src/common/pa_allocation.c +++ b/3rdparty/portaudio/src/common/pa_allocation.c @@ -27,13 +27,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -78,8 +78,8 @@ static struct PaUtilAllocationGroupLink *AllocateLinks( long count, { struct PaUtilAllocationGroupLink *result; int i; - - result = (struct PaUtilAllocationGroupLink *)PaUtil_AllocateMemory( + + result = (struct PaUtilAllocationGroupLink *)PaUtil_AllocateZeroInitializedMemory( sizeof(struct PaUtilAllocationGroupLink) * count ); if( result ) { @@ -95,7 +95,7 @@ static struct PaUtilAllocationGroupLink *AllocateLinks( long count, } result[count-1].next = nextSpare; } - + return result; } @@ -109,7 +109,8 @@ PaUtilAllocationGroup* PaUtil_CreateAllocationGroup( void ) links = AllocateLinks( PA_INITIAL_LINK_COUNT_, 0, 0 ); if( links != 0 ) { - result = (PaUtilAllocationGroup*)PaUtil_AllocateMemory( sizeof(PaUtilAllocationGroup) ); + result = (PaUtilAllocationGroup*)PaUtil_AllocateZeroInitializedMemory( + sizeof(PaUtilAllocationGroup) ); if( result ) { result->linkCount = PA_INITIAL_LINK_COUNT_; @@ -143,11 +144,11 @@ void PaUtil_DestroyAllocationGroup( PaUtilAllocationGroup* group ) } -void* PaUtil_GroupAllocateMemory( PaUtilAllocationGroup* group, long size ) +void* PaUtil_GroupAllocateZeroInitializedMemory( PaUtilAllocationGroup* group, long size ) { struct PaUtilAllocationGroupLink *links, *link; void *result = 0; - + /* allocate more links if necessary */ if( !group->spareLinks ) { @@ -163,7 +164,7 @@ void* PaUtil_GroupAllocateMemory( PaUtilAllocationGroup* group, long size ) if( group->spareLinks ) { - result = PaUtil_AllocateMemory( size ); + result = PaUtil_AllocateZeroInitializedMemory( size ); if( result ) { link = group->spareLinks; @@ -176,7 +177,7 @@ void* PaUtil_GroupAllocateMemory( PaUtilAllocationGroup* group, long size ) } } - return result; + return result; } @@ -208,7 +209,7 @@ void PaUtil_GroupFreeMemory( PaUtilAllocationGroup* group, void *buffer ) break; } - + previous = current; current = current->next; } @@ -240,4 +241,3 @@ void PaUtil_FreeAllAllocations( PaUtilAllocationGroup* group ) group->allocations = 0; } } - diff --git a/3rdparty/portaudio/src/common/pa_allocation.h b/3rdparty/portaudio/src/common/pa_allocation.h index bd1f4b0fd4f..226c116e12e 100644 --- a/3rdparty/portaudio/src/common/pa_allocation.h +++ b/3rdparty/portaudio/src/common/pa_allocation.h @@ -29,13 +29,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -44,12 +44,12 @@ @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. + can be useful 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 @@ -80,11 +80,12 @@ PaUtilAllocationGroup* PaUtil_CreateAllocationGroup( void ); */ void PaUtil_DestroyAllocationGroup( PaUtilAllocationGroup* group ); -/** Allocate a block of memory though an allocation group. +/** Allocate a block of memory through the specified allocation group. +The allocated block is zero-initialized. */ -void* PaUtil_GroupAllocateMemory( PaUtilAllocationGroup* group, long size ); +void* PaUtil_GroupAllocateZeroInitializedMemory( PaUtilAllocationGroup* group, long size ); -/** Free a block of memory that was previously allocated though an allocation +/** Free a block of memory that was allocated through the specified 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. diff --git a/3rdparty/portaudio/src/common/pa_converters.c b/3rdparty/portaudio/src/common/pa_converters.c index 2107f5e2891..29bbf2b3f7b 100644 --- a/3rdparty/portaudio/src/common/pa_converters.c +++ b/3rdparty/portaudio/src/common/pa_converters.c @@ -26,13 +26,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -40,17 +40,17 @@ @ingroup common_src @brief Conversion function implementations. - + If the C9x function lrintf() is available, define PA_USE_C99_LRINTF to use it @todo Consider whether functions which dither but don't clip should exist, V18 automatically enabled clipping whenever dithering was selected. Perhaps - we should do the same. + we should do the same. see: "require clipping for dithering sample conversion functions?" http://www.portaudio.com/trac/ticket/112 @todo implement the converters marked IMPLEMENT ME: Int32_To_Int24_Dither, - Int32_To_UInt8_Dither, Int24_To_Int16_Dither, Int24_To_Int8_Dither, + Int32_To_UInt8_Dither, Int24_To_Int16_Dither, Int24_To_Int8_Dither, Int24_To_UInt8_Dither, Int16_To_Int8_Dither, Int16_To_UInt8_Dither see: "some conversion functions are not implemented in pa_converters.c" http://www.portaudio.com/trac/ticket/35 @@ -74,7 +74,7 @@ PaSampleFormat PaUtil_SelectClosestAvailableFormat( format &= ~paNonInterleaved; availableFormats &= ~paNonInterleaved; - + if( (format & availableFormats) == 0 ) { /* NOTE: this code depends on the sample format constants being in @@ -97,7 +97,7 @@ PaSampleFormat PaUtil_SelectClosestAvailableFormat( { result = 0; } - + if( result == 0 ){ /* scan for worse formats */ result = format; @@ -110,7 +110,7 @@ PaSampleFormat PaUtil_SelectClosestAvailableFormat( if( (result & availableFormats) == 0 ) result = paSampleFormatNotSupported; } - + }else{ result = format; } @@ -286,7 +286,7 @@ PaUtilConverterTable paConverters = { 0, /* PaUtilConverter *Int24_To_Int8_Dither; */ 0, /* PaUtilConverter *Int24_To_UInt8; */ 0, /* PaUtilConverter *Int24_To_UInt8_Dither; */ - + 0, /* PaUtilConverter *Int16_To_Float32; */ 0, /* PaUtilConverter *Int16_To_Int32; */ 0, /* PaUtilConverter *Int16_To_Int24; */ @@ -348,9 +348,9 @@ static void Float32_To_Int32( *dest = lrintf(scaled-0.5f); #else double scaled = *src * 0x7FFFFFFF; - *dest = (PaInt32) scaled; + *dest = (PaInt32) scaled; #endif - + src += sourceStride; dest += destinationStride; } @@ -395,7 +395,7 @@ static void Float32_To_Int32_Clip( float *src = (float*)sourceBuffer; PaInt32 *dest = (PaInt32*)destinationBuffer; (void) ditherGenerator; /* unused parameter */ - + while( count-- ) { /* REVIEW */ @@ -458,13 +458,13 @@ static void Float32_To_Int24( PaInt32 temp; (void) ditherGenerator; /* unused parameter */ - + while( count-- ) { /* convert to 32 bit and drop the low 8 bits */ double scaled = (double)(*src) * 2147483647.0; temp = (PaInt32) scaled; - + #if defined(PA_LITTLE_ENDIAN) dest[0] = (unsigned char)(temp >> 8); dest[1] = (unsigned char)(temp >> 16); @@ -498,7 +498,7 @@ static void Float32_To_Int24_Dither( double dither = PaUtil_GenerateFloatTriangularDither( ditherGenerator ); /* use smaller scaler to prevent overflow when we add the dither */ double dithered = ((double)*src * (2147483646.0)) + dither; - + temp = (PaInt32) dithered; #if defined(PA_LITTLE_ENDIAN) @@ -528,7 +528,7 @@ static void Float32_To_Int24_Clip( PaInt32 temp; (void) ditherGenerator; /* unused parameter */ - + while( count-- ) { /* convert to 32 bit and drop the low 8 bits */ @@ -561,16 +561,16 @@ static void Float32_To_Int24_DitherClip( float *src = (float*)sourceBuffer; unsigned char *dest = (unsigned char*)destinationBuffer; PaInt32 temp; - + while( count-- ) { /* convert to 32 bit and drop the low 8 bits */ - + double dither = PaUtil_GenerateFloatTriangularDither( ditherGenerator ); /* use smaller scaler to prevent overflow when we add the dither */ double dithered = ((double)*src * (2147483646.0)) + dither; PA_CLIP_( dithered, -2147483648., 2147483647. ); - + temp = (PaInt32) dithered; #if defined(PA_LITTLE_ENDIAN) @@ -728,7 +728,7 @@ static void Float32_To_Int8_Dither( { float *src = (float*)sourceBuffer; signed char *dest = (signed char*)destinationBuffer; - + while( count-- ) { float dither = PaUtil_GenerateFloatTriangularDither( ditherGenerator ); @@ -819,7 +819,7 @@ static void Float32_To_UInt8_Dither( { float *src = (float*)sourceBuffer; unsigned char *dest = (unsigned char*)destinationBuffer; - + while( count-- ) { float dither = PaUtil_GenerateFloatTriangularDither( ditherGenerator ); @@ -827,7 +827,7 @@ static void Float32_To_UInt8_Dither( float dithered = (*src * (126.0f)) + dither; PaInt32 samp = (PaInt32) dithered; *dest = (unsigned char) (128 + samp); - + src += sourceStride; dest += destinationStride; } @@ -910,10 +910,10 @@ static void Int32_To_Int24( PaInt32 *src = (PaInt32*)sourceBuffer; unsigned char *dest = (unsigned char*)destinationBuffer; (void) ditherGenerator; /* unused parameter */ - - while( count-- ) + + while( count-- ) { - /* REVIEW */ + /* REVIEW */ #if defined(PA_LITTLE_ENDIAN) dest[0] = (unsigned char)(*src >> 8); dest[1] = (unsigned char)(*src >> 16); @@ -1041,7 +1041,7 @@ static void Int32_To_UInt8( while( count-- ) { - (*dest) = (unsigned char)(((*src) >> 24) + 128); + (*dest) = (unsigned char)(((*src) >> 24) + 128); src += sourceStride; dest += destinationStride; @@ -1055,16 +1055,16 @@ static void Int32_To_UInt8_Dither( void *sourceBuffer, signed int sourceStride, unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) { - PaInt32 *src = (PaInt32*)sourceBuffer; - unsigned char *dest = (unsigned char*)destinationBuffer; + /* PaInt32 *src = (PaInt32*)sourceBuffer; + unsigned char *dest = (unsigned char*)destinationBuffer; */ (void)ditherGenerator; /* unused parameter */ while( count-- ) { /* IMPLEMENT ME */ - src += sourceStride; - dest += destinationStride; + /* src += sourceStride; + dest += destinationStride; */ } } @@ -1080,12 +1080,12 @@ static void Int24_To_Float32( PaInt32 temp; (void) ditherGenerator; /* unused parameter */ - + while( count-- ) { #if defined(PA_LITTLE_ENDIAN) - temp = (((PaInt32)src[0]) << 8); + temp = (((PaInt32)src[0]) << 8); temp = temp | (((PaInt32)src[1]) << 16); temp = temp | (((PaInt32)src[2]) << 24); #elif defined(PA_BIG_ENDIAN) @@ -1113,12 +1113,12 @@ static void Int24_To_Int32( PaInt32 temp; (void) ditherGenerator; /* unused parameter */ - + while( count-- ) { #if defined(PA_LITTLE_ENDIAN) - temp = (((PaInt32)src[0]) << 8); + temp = (((PaInt32)src[0]) << 8); temp = temp | (((PaInt32)src[1]) << 16); temp = temp | (((PaInt32)src[2]) << 24); #elif defined(PA_BIG_ENDIAN) @@ -1143,20 +1143,20 @@ static void Int24_To_Int16( { unsigned char *src = (unsigned char*)sourceBuffer; PaInt16 *dest = (PaInt16*)destinationBuffer; - + PaInt16 temp; (void) ditherGenerator; /* unused parameter */ - + while( count-- ) { - + #if defined(PA_LITTLE_ENDIAN) - /* src[0] is discarded */ + /* src[0] is discarded */ temp = (((PaInt16)src[1])); temp = temp | (PaInt16)(((PaInt16)src[2]) << 8); #elif defined(PA_BIG_ENDIAN) - /* src[2] is discarded */ + /* src[2] is discarded */ temp = (PaInt16)(((PaInt16)src[0]) << 8); temp = temp | (((PaInt16)src[1])); #endif @@ -1184,7 +1184,7 @@ static void Int24_To_Int16_Dither( { #if defined(PA_LITTLE_ENDIAN) - temp = (((PaInt32)src[0]) << 8); + temp = (((PaInt32)src[0]) << 8); temp = temp | (((PaInt32)src[1]) << 16); temp = temp | (((PaInt32)src[2]) << 24); #elif defined(PA_BIG_ENDIAN) @@ -1211,20 +1211,20 @@ static void Int24_To_Int8( { unsigned char *src = (unsigned char*)sourceBuffer; signed char *dest = (signed char*)destinationBuffer; - + (void) ditherGenerator; /* unused parameter */ - + while( count-- ) - { - + { + #if defined(PA_LITTLE_ENDIAN) - /* src[0] is discarded */ - /* src[1] is discarded */ + /* src[0] is discarded */ + /* src[1] is discarded */ *dest = src[2]; #elif defined(PA_BIG_ENDIAN) - /* src[2] is discarded */ - /* src[1] is discarded */ - *dest = src[0]; + /* src[2] is discarded */ + /* src[1] is discarded */ + *dest = src[0]; #endif src += sourceStride * 3; @@ -1241,14 +1241,14 @@ static void Int24_To_Int8_Dither( { unsigned char *src = (unsigned char*)sourceBuffer; signed char *dest = (signed char*)destinationBuffer; - + PaInt32 temp, dither; while( count-- ) { #if defined(PA_LITTLE_ENDIAN) - temp = (((PaInt32)src[0]) << 8); + temp = (((PaInt32)src[0]) << 8); temp = temp | (((PaInt32)src[1]) << 16); temp = temp | (((PaInt32)src[2]) << 24); #elif defined(PA_BIG_ENDIAN) @@ -1275,20 +1275,20 @@ static void Int24_To_UInt8( { unsigned char *src = (unsigned char*)sourceBuffer; unsigned char *dest = (unsigned char*)destinationBuffer; - + (void) ditherGenerator; /* unused parameter */ - + while( count-- ) { - + #if defined(PA_LITTLE_ENDIAN) - /* src[0] is discarded */ - /* src[1] is discarded */ + /* src[0] is discarded */ + /* src[1] is discarded */ *dest = (unsigned char)(src[2] + 128); #elif defined(PA_BIG_ENDIAN) *dest = (unsigned char)(src[0] + 128); - /* src[1] is discarded */ - /* src[2] is discarded */ + /* src[1] is discarded */ + /* src[2] is discarded */ #endif src += sourceStride * 3; @@ -1325,7 +1325,7 @@ static void Int16_To_Float32( while( count-- ) { - float samp = *src * const_1_div_32768_; /* FIXME: i'm concerned about this being asymetrical with float->int16 -rb */ + float samp = *src * const_1_div_32768_; /* FIXME: i'm concerned about this being asymmetrical with float->int16 -rb */ *dest = samp; src += sourceStride; @@ -1349,7 +1349,7 @@ static void Int16_To_Int32( /* REVIEW: we should consider something like (*src << 16) | (*src & 0xFFFF) */ - + *dest = *src << 16; src += sourceStride; @@ -1369,11 +1369,11 @@ static void Int16_To_Int24( PaInt16 temp; (void) ditherGenerator; /* unused parameter */ - + while( count-- ) { temp = *src; - + #if defined(PA_LITTLE_ENDIAN) dest[0] = 0; dest[1] = (unsigned char)(temp); @@ -1416,16 +1416,16 @@ static void Int16_To_Int8_Dither( void *sourceBuffer, signed int sourceStride, unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) { - PaInt16 *src = (PaInt16*)sourceBuffer; - signed char *dest = (signed char*)destinationBuffer; + /* PaInt16 *src = (PaInt16*)sourceBuffer; + signed char *dest = (signed char*)destinationBuffer; */ (void)ditherGenerator; /* unused parameter */ while( count-- ) { /* IMPLEMENT ME */ - src += sourceStride; - dest += destinationStride; + /* src += sourceStride; + dest += destinationStride; */ } } @@ -1442,7 +1442,7 @@ static void Int16_To_UInt8( while( count-- ) { - (*dest) = (unsigned char)(((*src) >> 8) + 128); + (*dest) = (unsigned char)(((*src) >> 8) + 128); src += sourceStride; dest += destinationStride; @@ -1456,16 +1456,16 @@ static void Int16_To_UInt8_Dither( void *sourceBuffer, signed int sourceStride, unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) { - PaInt16 *src = (PaInt16*)sourceBuffer; - unsigned char *dest = (unsigned char*)destinationBuffer; + /* PaInt16 *src = (PaInt16*)sourceBuffer; + unsigned char *dest = (unsigned char*)destinationBuffer; */ (void)ditherGenerator; /* unused parameter */ while( count-- ) { /* IMPLEMENT ME */ - src += sourceStride; - dest += destinationStride; + /* src += sourceStride; + dest += destinationStride; */ } } @@ -1503,7 +1503,7 @@ static void Int8_To_Int32( while( count-- ) { - (*dest) = (*src) << 24; + (*dest) = (*src) << 24; src += sourceStride; dest += destinationStride; @@ -1613,7 +1613,7 @@ static void UInt8_To_Int32( while( count-- ) { - (*dest) = (*src - 128) << 24; + (*dest) = (*src - 128) << 24; src += sourceStride; dest += destinationStride; @@ -1627,11 +1627,11 @@ static void UInt8_To_Int24( void *sourceBuffer, signed int sourceStride, unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) { - unsigned char *src = (unsigned char*)sourceBuffer; + unsigned char *src = (unsigned char*)sourceBuffer; unsigned char *dest = (unsigned char*)destinationBuffer; (void) ditherGenerator; /* unused parameters */ - - while( count-- ) + + while( count-- ) { #if defined(PA_LITTLE_ENDIAN) @@ -1643,10 +1643,10 @@ static void UInt8_To_Int24( dest[1] = 0; dest[2] = 0; #endif - + src += sourceStride; - dest += destinationStride * 3; - } + dest += destinationStride * 3; + } } /* -------------------------------------------------------------------------- */ @@ -1698,7 +1698,7 @@ static void Copy_8_To_8( { unsigned char *src = (unsigned char*)sourceBuffer; unsigned char *dest = (unsigned char*)destinationBuffer; - + (void) ditherGenerator; /* unused parameter */ while( count-- ) @@ -1719,9 +1719,9 @@ static void Copy_16_To_16( { PaUint16 *src = (PaUint16 *)sourceBuffer; PaUint16 *dest = (PaUint16 *)destinationBuffer; - + (void) ditherGenerator; /* unused parameter */ - + while( count-- ) { *dest = *src; @@ -1742,7 +1742,7 @@ static void Copy_24_To_24( unsigned char *dest = (unsigned char*)destinationBuffer; (void) ditherGenerator; /* unused parameter */ - + while( count-- ) { dest[0] = src[0]; @@ -1765,7 +1765,7 @@ static void Copy_32_To_32( PaUint32 *src = (PaUint32 *)sourceBuffer; (void) ditherGenerator; /* unused parameter */ - + while( count-- ) { *dest = *src; @@ -1787,7 +1787,7 @@ PaUtilConverterTable paConverters = { Float32_To_Int24_Dither, /* PaUtilConverter *Float32_To_Int24_Dither; */ Float32_To_Int24_Clip, /* PaUtilConverter *Float32_To_Int24_Clip; */ Float32_To_Int24_DitherClip, /* PaUtilConverter *Float32_To_Int24_DitherClip; */ - + Float32_To_Int16, /* PaUtilConverter *Float32_To_Int16; */ Float32_To_Int16_Dither, /* PaUtilConverter *Float32_To_Int16_Dither; */ Float32_To_Int16_Clip, /* PaUtilConverter *Float32_To_Int16_Clip; */ diff --git a/3rdparty/portaudio/src/common/pa_converters.h b/3rdparty/portaudio/src/common/pa_converters.h index 469f075d6f4..96edf1c92cf 100644 --- a/3rdparty/portaudio/src/common/pa_converters.h +++ b/3rdparty/portaudio/src/common/pa_converters.h @@ -28,13 +28,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -59,7 +59,7 @@ 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. + higher quality formats are considered before lower quality formats. @param availableFormats A variable containing the logical OR of all available formats. @param format The desired format. @@ -119,7 +119,7 @@ PaUtilConverter* PaUtil_SelectConverter( PaSampleFormat sourceFormat, 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 @@ -145,7 +145,7 @@ typedef struct{ 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; @@ -193,7 +193,7 @@ typedef struct{ PaUtilConverter *Int8_To_Int24; PaUtilConverter *Int8_To_Int16; PaUtilConverter *Int8_To_UInt8; - + PaUtilConverter *UInt8_To_Float32; PaUtilConverter *UInt8_To_Int32; PaUtilConverter *UInt8_To_Int24; @@ -211,7 +211,7 @@ typedef struct{ 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 + no conversion function is available. User code may substitute optimised conversion functions by assigning different function pointers to these fields. @@ -242,7 +242,7 @@ typedef struct{ /** 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 + with default conversion functions. User code may substitute optimised conversion functions by assigning different function pointers to these fields. diff --git a/3rdparty/portaudio/src/common/pa_cpuload.c b/3rdparty/portaudio/src/common/pa_cpuload.c index 4adf21adc5b..de57db26ab2 100644 --- a/3rdparty/portaudio/src/common/pa_cpuload.c +++ b/3rdparty/portaudio/src/common/pa_cpuload.c @@ -27,13 +27,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -94,7 +94,7 @@ void PaUtil_EndCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer, unsigned lon #define LOWPASS_COEFFICIENT_1 (0.99999 - LOWPASS_COEFFICIENT_0) measurer->averageLoad = (LOWPASS_COEFFICIENT_0 * measurer->averageLoad) + - (LOWPASS_COEFFICIENT_1 * measuredLoad); + (LOWPASS_COEFFICIENT_1 * measuredLoad); } } diff --git a/3rdparty/portaudio/src/common/pa_cpuload.h b/3rdparty/portaudio/src/common/pa_cpuload.h index 2a323aa7905..8d3f618701a 100644 --- a/3rdparty/portaudio/src/common/pa_cpuload.h +++ b/3rdparty/portaudio/src/common/pa_cpuload.h @@ -29,13 +29,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -68,5 +68,5 @@ double PaUtil_GetCpuLoad( PaUtilCpuLoadMeasurer* measurer ); #ifdef __cplusplus } -#endif /* __cplusplus */ +#endif /* __cplusplus */ #endif /* PA_CPULOAD_H */ diff --git a/3rdparty/portaudio/src/common/pa_debugprint.c b/3rdparty/portaudio/src/common/pa_debugprint.c index f34d4bbf985..3e4024c48fd 100644 --- a/3rdparty/portaudio/src/common/pa_debugprint.c +++ b/3rdparty/portaudio/src/common/pa_debugprint.c @@ -43,11 +43,11 @@ @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. + 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 @@ -57,8 +57,8 @@ // for OutputDebugStringA #if defined(_MSC_VER) && defined(PA_ENABLE_MSVC_DEBUG_OUTPUT) - #define WIN32_LEAN_AND_MEAN // exclude rare headers - #include "windows.h" + #define WIN32_LEAN_AND_MEAN // exclude rare headers + #include "windows.h" #endif // User callback @@ -71,36 +71,36 @@ void PaUtil_SetDebugPrintFunction(PaUtilLogCallback cb) } /* - If your platform doesn’t have vsnprintf, you are stuck with a + If your platform doesn't 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 + /* 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 + #define VSNPRINTF vsnprintf #endif #define PA_LOG_BUF_SIZE 2048 void PaUtil_DebugPrint( const char *format, ... ) { - // Optional logging into Output console of Visual Studio + // 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); - } + { + 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 + // Output to User-Callback if (userCB != NULL) { char strdump[PA_LOG_BUF_SIZE]; @@ -112,7 +112,7 @@ void PaUtil_DebugPrint( const char *format, ... ) va_end(ap); } else - // Standard output to stderr + // Standard output to stderr { va_list ap; va_start(ap, format); diff --git a/3rdparty/portaudio/src/common/pa_debugprint.h b/3rdparty/portaudio/src/common/pa_debugprint.h index 5fba7667dc3..ca817240053 100644 --- a/3rdparty/portaudio/src/common/pa_debugprint.h +++ b/3rdparty/portaudio/src/common/pa_debugprint.h @@ -101,7 +101,7 @@ void PaUtil_DebugPrint( const char *format, ... ); #ifdef PA_LOG_API_CALLS -#define PA_LOGAPI(x) PaUtil_DebugPrint x +#define PA_LOGAPI(x) PaUtil_DebugPrint x #define PA_LOGAPI_ENTER(functionName) PaUtil_DebugPrint( functionName " called.\n" ) @@ -110,16 +110,16 @@ void PaUtil_DebugPrint( const char *format, ... ); #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 ) ) + 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 ) + 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( functionName " returned:\n" ); \ + if( result > 0 ) \ PaUtil_DebugPrint("\t" positiveResultFormatString "\n", result ); \ else \ PaUtil_DebugPrint("\tPaError: %d ( %s )\n", result, Pa_GetErrorText( result ) ) @@ -133,7 +133,7 @@ void PaUtil_DebugPrint( const char *format, ... ); #define PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( functionName, positiveResultFormatString, result ) #endif - + typedef void (*PaUtilLogCallback ) (const char *log); /** diff --git a/3rdparty/portaudio/src/common/pa_dither.c b/3rdparty/portaudio/src/common/pa_dither.c index 140e480afbc..0d1666a7741 100644 --- a/3rdparty/portaudio/src/common/pa_dither.c +++ b/3rdparty/portaudio/src/common/pa_dither.c @@ -26,13 +26,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -72,10 +72,10 @@ PaInt32 PaUtil_Generate16BitTriangularDither( PaUtilTriangularDitherGenerator *s /* 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. + * 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_); @@ -100,7 +100,7 @@ float PaUtil_GenerateFloatTriangularDither( PaUtilTriangularDitherGenerator *sta /* 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. + * Also shift an extra bit for the high pass filter. */ current = (((PaInt32)state->randSeed1)>>DITHER_SHIFT_) + (((PaInt32)state->randSeed2)>>DITHER_SHIFT_); @@ -137,7 +137,7 @@ things like this: r3=(r1 & 0x7F)<<8; instead of calling rand() again. 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 wi= 1.0f/w; float d = wi / RAND_MAX; //dither amplitude (2 lsb) float o = wi * 0.5f; //remove dc offset float in, tmp; @@ -148,19 +148,19 @@ things like this: r3=(r1 & 0x7F)<<8; instead of calling rand() again. 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 - + 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; + s2 = s1; s1 = in - wi * (float)out; //error --- +-- paul.kellett@maxim.abel.co.uk http://www.maxim.abel.co.uk */ @@ -172,7 +172,7 @@ http://www.maxim.abel.co.uk Type : First order error feedforward dithering code References : Posted by Jon Watte -Notes : +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. @@ -183,36 +183,36 @@ 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; -} +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; +} */ diff --git a/3rdparty/portaudio/src/common/pa_dither.h b/3rdparty/portaudio/src/common/pa_dither.h index 12ffc4fc67f..4f811230168 100644 --- a/3rdparty/portaudio/src/common/pa_dither.h +++ b/3rdparty/portaudio/src/common/pa_dither.h @@ -28,13 +28,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ diff --git a/3rdparty/portaudio/src/common/pa_endianness.h b/3rdparty/portaudio/src/common/pa_endianness.h index 9e8e059624c..e0748369242 100644 --- a/3rdparty/portaudio/src/common/pa_endianness.h +++ b/3rdparty/portaudio/src/common/pa_endianness.h @@ -28,13 +28,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -54,7 +54,7 @@ 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. + and runtime endianness and raise an assertion if they don't match. */ @@ -65,25 +65,25 @@ extern "C" /* 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 */ + /* we need to do some endian detection that is sensitive to hardware 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 + #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 + #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. */ + detect well-known architectures. */ #if defined(PA_LITTLE_ENDIAN) || defined(PA_BIG_ENDIAN) /* endianness define has been set externally, such as by autoconf */ diff --git a/3rdparty/portaudio/src/common/pa_front.c b/3rdparty/portaudio/src/common/pa_front.c index 188cee9e557..89b4335b8d4 100644 --- a/3rdparty/portaudio/src/common/pa_front.c +++ b/3rdparty/portaudio/src/common/pa_front.c @@ -74,7 +74,7 @@ #include "pa_types.h" #include "pa_hostapi.h" #include "pa_stream.h" -#include "pa_trace.h" /* still usefull?*/ +#include "pa_trace.h" /* still useful?*/ #include "pa_debugprint.h" #ifndef PA_GIT_REVISION @@ -91,7 +91,7 @@ * This is incremented when we add functionality in a backwards-compatible manner. * Or it is set to zero when paVersionMajor is incremented. */ -#define paVersionMinor 6 +#define paVersionMinor 7 /** * This is incremented when we make backwards-compatible bug fixes. @@ -106,11 +106,8 @@ */ #define paVersion paMakeVersionNumber(paVersionMajor, paVersionMinor, paVersionSubMinor) -#define STRINGIFY(x) #x -#define TOSTRING(x) STRINGIFY(x) - -#define PA_VERSION_STRING_ TOSTRING(paVersionMajor) "." TOSTRING(paVersionMinor) "." TOSTRING(paVersionSubMinor) -#define PA_VERSION_TEXT_ "PortAudio V" PA_VERSION_STRING_ "-devel, revision " TOSTRING(PA_GIT_REVISION) +#define PA_VERSION_STRING_ PA_STRINGIZE(paVersionMajor) "." PA_STRINGIZE(paVersionMinor) "." PA_STRINGIZE(paVersionSubMinor) +#define PA_VERSION_TEXT_ "PortAudio V" PA_VERSION_STRING_ "-devel, revision " PA_STRINGIZE(PA_GIT_REVISION) int Pa_GetVersion( void ) { @@ -126,11 +123,11 @@ static PaVersionInfo versionInfo_ = { /*.versionMajor =*/ paVersionMajor, /*.versionMinor =*/ paVersionMinor, /*.versionSubMinor =*/ paVersionSubMinor, - /*.versionControlRevision =*/ TOSTRING(PA_GIT_REVISION), + /*.versionControlRevision =*/ PA_STRINGIZE(PA_GIT_REVISION), /*.versionText =*/ PA_VERSION_TEXT_ }; -const PaVersionInfo* Pa_GetVersionInfo() +const PaVersionInfo* Pa_GetVersionInfo( void ) { return &versionInfo_; } @@ -204,7 +201,7 @@ static PaError InitializeHostApis( void ) initializerCount = CountHostApiInitializers(); - hostApis_ = (PaUtilHostApiRepresentation**)PaUtil_AllocateMemory( + hostApis_ = (PaUtilHostApiRepresentation**)PaUtil_AllocateZeroInitializedMemory( sizeof(PaUtilHostApiRepresentation*) * initializerCount ); if( !hostApis_ ) { @@ -457,10 +454,10 @@ const char *Pa_GetErrorText( PaError errorCode ) case paIncompatibleStreamHostApi: result = "Incompatible stream host API"; break; case paBadBufferPtr: result = "Bad buffer pointer"; break; default: - if( errorCode > 0 ) - result = "Invalid error code (value greater than zero)"; + if( errorCode > 0 ) + result = "Invalid error code (value greater than zero)"; else - result = "Invalid error code"; + result = "Invalid error code"; break; } return result; @@ -637,7 +634,7 @@ const PaHostApiInfo* Pa_GetHostApiInfo( PaHostApiIndex hostApi ) } - return info; + return info; } @@ -805,7 +802,7 @@ static int SampleFormatIsValid( PaSampleFormat format ) } /* - NOTE: make sure this validation list is kept syncronised with the one in + NOTE: make sure this validation list is kept synchronised with the one in pa_hostapi.h ValidateOpenStreamParameters() checks that parameters to Pa_OpenStream() @@ -865,7 +862,7 @@ static int SampleFormatIsValid( PaSampleFormat format ) - 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.) + - is not an 'absurd' rate (less than 1000. or greater than 768000.) - sampleRate is NOT validated against device capabilities PaStreamFlags streamFlags @@ -884,9 +881,9 @@ static PaError ValidateOpenStreamParameters( PaDeviceIndex *hostApiInputDevice, PaDeviceIndex *hostApiOutputDevice ) { - int inputHostApiIndex = -1, /* Surpress uninitialised var warnings: compiler does */ - outputHostApiIndex = -1; /* not see that if inputParameters and outputParame- */ - /* ters are both nonzero, these indices are set. */ + int inputHostApiIndex = -1; /* Suppress uninitialised var warnings: compiler does */ + int outputHostApiIndex = -1; /* not see that if inputParameters and outputParameters */ + /* are both nonzero, these indices are set. */ if( (inputParameters == NULL) && (outputParameters == NULL) ) { @@ -1006,7 +1003,7 @@ static PaError ValidateOpenStreamParameters( /* Check for absurd sample rates. */ - if( (sampleRate < 1000.0) || (sampleRate > 384000.0) ) + if( (sampleRate < 1000.0) || (sampleRate > 768000.0) ) return paInvalidSampleRate; if( ((streamFlags & ~paPlatformSpecificFlags) & ~(paClipOff | paDitherOff | paNeverDropInput | paPrimeOutputBuffersUsingStreamCallback ) ) != 0 ) @@ -1016,7 +1013,7 @@ static PaError ValidateOpenStreamParameters( { /* must be a callback stream */ if( !streamCallback ) - return paInvalidFlag; + return paInvalidFlag; /* must be a full duplex stream */ if( (inputParameters == NULL) || (outputParameters == NULL) ) @@ -1195,7 +1192,7 @@ PaError Pa_OpenStream( PaStream** stream, } /* Check for parameter errors. - NOTE: make sure this validation list is kept syncronised with the one + NOTE: make sure this validation list is kept synchronised with the one in pa_hostapi.h */ @@ -1296,8 +1293,8 @@ PaError Pa_OpenDefaultStream( PaStream** stream, if( inputChannelCount > 0 ) { hostApiInputParameters.device = Pa_GetDefaultInputDevice(); - if( hostApiInputParameters.device == paNoDevice ) - return paDeviceUnavailable; + if( hostApiInputParameters.device == paNoDevice ) + return paDeviceUnavailable; hostApiInputParameters.channelCount = inputChannelCount; hostApiInputParameters.sampleFormat = sampleFormat; @@ -1319,8 +1316,8 @@ PaError Pa_OpenDefaultStream( PaStream** stream, if( outputChannelCount > 0 ) { hostApiOutputParameters.device = Pa_GetDefaultOutputDevice(); - if( hostApiOutputParameters.device == paNoDevice ) - return paDeviceUnavailable; + if( hostApiOutputParameters.device == paNoDevice ) + return paDeviceUnavailable; hostApiOutputParameters.channelCount = outputChannelCount; hostApiOutputParameters.sampleFormat = sampleFormat; @@ -1808,4 +1805,3 @@ PaError Pa_GetSampleSize( PaSampleFormat format ) return (PaError) result; } - diff --git a/3rdparty/portaudio/src/common/pa_gitrevision.h b/3rdparty/portaudio/src/common/pa_gitrevision.h index 2a6cfca8d25..7d47425c71d 100644 --- a/3rdparty/portaudio/src/common/pa_gitrevision.h +++ b/3rdparty/portaudio/src/common/pa_gitrevision.h @@ -1 +1 @@ -#define PA_GIT_REVISION 396fe4b6699ae929d3a685b3ef8a7e97396139a4 +#define PA_GIT_REVISION unknown diff --git a/3rdparty/portaudio/src/common/pa_hostapi.h b/3rdparty/portaudio/src/common/pa_hostapi.h index 54b527ea819..4ac3ab60e92 100644 --- a/3rdparty/portaudio/src/common/pa_hostapi.h +++ b/3rdparty/portaudio/src/common/pa_hostapi.h @@ -29,20 +29,20 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * 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 + @brief Interfaces and representation structures used by pa_front.c to manage and communicate with host API implementations. */ @@ -51,12 +51,12 @@ /** 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 +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 +0 or 1. Undefined symbols are defaulted to 0. Symbols that are neither 0 nor 1 are defaulted to 1. */ @@ -65,7 +65,7 @@ are defaulted to 1. #elif (PA_USE_SKELETON != 0) && (PA_USE_SKELETON != 1) #undef PA_USE_SKELETON #define PA_USE_SKELETON 1 -#endif +#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_ is no longer supported, please remove definition and use PA_USE_ instead" @@ -76,35 +76,35 @@ are defaulted to 1. #elif (PA_USE_ASIO != 0) && (PA_USE_ASIO != 1) #undef PA_USE_ASIO #define PA_USE_ASIO 1 -#endif +#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 +#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 +#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 +#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 +#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) @@ -116,42 +116,42 @@ are defaulted to 1. #elif (PA_USE_OSS != 0) && (PA_USE_OSS != 1) #undef PA_USE_OSS #define PA_USE_OSS 1 -#endif +#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 +#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 +#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 +#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 +#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 +#endif #ifdef __cplusplus extern "C" @@ -216,13 +216,13 @@ typedef struct PaUtilHostApiRepresentation { 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 @@ -233,7 +233,7 @@ typedef struct PaUtilHostApiRepresentation { - 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 @@ -243,30 +243,30 @@ typedef struct PaUtilHostApiRepresentation { 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 @@ -278,7 +278,7 @@ typedef struct PaUtilHostApiRepresentation { 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 @@ -287,7 +287,7 @@ typedef struct PaUtilHostApiRepresentation { 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 @@ -327,11 +327,11 @@ typedef struct 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 + + 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 @@ -341,11 +341,11 @@ typedef PaError PaUtilHostApiInitializer( PaUtilHostApiRepresentation**, PaHostA /** 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(). - + 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 + 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). diff --git a/3rdparty/portaudio/src/common/pa_memorybarrier.h b/3rdparty/portaudio/src/common/pa_memorybarrier.h index 2879ce33adc..6f07b603e97 100644 --- a/3rdparty/portaudio/src/common/pa_memorybarrier.h +++ b/3rdparty/portaudio/src/common/pa_memorybarrier.h @@ -30,13 +30,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -61,42 +61,52 @@ ****************/ #if defined(__APPLE__) -# include - /* 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() +/* Support for the atomic library was added in C11. + */ +# if (__STDC_VERSION__ < 201112L) || defined(__STDC_NO_ATOMICS__) +# include + /* 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. + These were deprecated in MacOS 10.12. */ +# define PaUtil_FullMemoryBarrier() OSMemoryBarrier() +# define PaUtil_ReadMemoryBarrier() OSMemoryBarrier() +# define PaUtil_WriteMemoryBarrier() OSMemoryBarrier() +# else +# include +# define PaUtil_FullMemoryBarrier() atomic_thread_fence(memory_order_seq_cst) +# define PaUtil_ReadMemoryBarrier() atomic_thread_fence(memory_order_acquire) +# define PaUtil_WriteMemoryBarrier() atomic_thread_fence(memory_order_release) +# endif #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() +# 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") +# 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") + 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 +# 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 @@ -117,12 +127,12 @@ # 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() +# 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. +# 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 diff --git a/3rdparty/portaudio/src/common/pa_process.c b/3rdparty/portaudio/src/common/pa_process.c index 0faf8414cfa..29fca64fa3a 100644 --- a/3rdparty/portaudio/src/common/pa_process.c +++ b/3rdparty/portaudio/src/common/pa_process.c @@ -27,13 +27,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -142,7 +142,7 @@ PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bp, } else /* unknown host buffer size */ { - bp->framesPerTempBuffer = PA_FRAMES_PER_TEMP_BUFFER_WHEN_HOST_BUFFER_SIZE_IS_UNKNOWN_; + bp->framesPerTempBuffer = PA_FRAMES_PER_TEMP_BUFFER_WHEN_HOST_BUFFER_SIZE_IS_UNKNOWN_; } } else @@ -198,7 +198,7 @@ PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bp, bp->framesInTempInputBuffer = bp->initialFramesInTempInputBuffer; bp->framesInTempOutputBuffer = bp->initialFramesInTempOutputBuffer; - + if( inputChannelCount > 0 ) { bytesPerSample = Pa_GetSampleSize( hostInputSampleFormat ); @@ -224,7 +224,7 @@ PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bp, } /* Under the assumption that no ADC in existence delivers better than 24bits resolution, - we disable dithering when host input format is paInt32 and user format is paInt24, + we disable dithering when host input format is paInt32 and user format is paInt24, since the host samples will just be padded with zeros anyway. */ tempInputStreamFlags = streamFlags; @@ -239,30 +239,33 @@ PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bp, PaUtil_SelectConverter( hostInputSampleFormat, userInputSampleFormat, tempInputStreamFlags ); bp->inputZeroer = PaUtil_SelectZeroer( userInputSampleFormat ); - + bp->userInputIsInterleaved = (userInputSampleFormat & paNonInterleaved)?0:1; - + bp->hostInputIsInterleaved = (hostInputSampleFormat & paNonInterleaved)?0:1; bp->userInputSampleFormatIsEqualToHost = ((userInputSampleFormat & ~paNonInterleaved) == (hostInputSampleFormat & ~paNonInterleaved)); tempInputBufferSize = bp->framesPerTempBuffer * bp->bytesPerUserInputSample * inputChannelCount; - - bp->tempInputBuffer = PaUtil_AllocateMemory( tempInputBufferSize ); + + bp->tempInputBuffer = PaUtil_AllocateZeroInitializedMemory( tempInputBufferSize ); if( bp->tempInputBuffer == 0 ) { result = paInsufficientMemory; goto error; } - + if( bp->framesInTempInputBuffer > 0 ) - memset( bp->tempInputBuffer, 0, tempInputBufferSize ); + { + /* NOTE: we depend on bp->tempInputBuffer being zero-initialized by the allocator. */ + /* memset( bp->tempInputBuffer, 0, tempInputBufferSize ); */ + } if( userInputSampleFormat & paNonInterleaved ) { bp->tempInputBufferPtrs = - (void **)PaUtil_AllocateMemory( sizeof(void*)*inputChannelCount ); + (void **)PaUtil_AllocateZeroInitializedMemory( sizeof(void*)*inputChannelCount ); if( bp->tempInputBufferPtrs == 0 ) { result = paInsufficientMemory; @@ -271,7 +274,7 @@ PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bp, } bp->hostInputChannels[0] = (PaUtilChannelDescriptor*) - PaUtil_AllocateMemory( sizeof(PaUtilChannelDescriptor) * inputChannelCount * 2); + PaUtil_AllocateZeroInitializedMemory( sizeof(PaUtilChannelDescriptor) * inputChannelCount * 2); if( bp->hostInputChannels[0] == 0 ) { result = paInsufficientMemory; @@ -319,7 +322,7 @@ PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bp, tempOutputBufferSize = bp->framesPerTempBuffer * bp->bytesPerUserOutputSample * outputChannelCount; - bp->tempOutputBuffer = PaUtil_AllocateMemory( tempOutputBufferSize ); + bp->tempOutputBuffer = PaUtil_AllocateZeroInitializedMemory( tempOutputBufferSize ); if( bp->tempOutputBuffer == 0 ) { result = paInsufficientMemory; @@ -327,12 +330,15 @@ PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bp, } if( bp->framesInTempOutputBuffer > 0 ) - memset( bp->tempOutputBuffer, 0, tempOutputBufferSize ); - + { + /* NOTE: we depend on bp->tempOutputBuffer being zero-initialized by the allocator. */ + /* memset( bp->tempOutputBuffer, 0, tempOutputBufferSize ); */ + } + if( userOutputSampleFormat & paNonInterleaved ) { bp->tempOutputBufferPtrs = - (void **)PaUtil_AllocateMemory( sizeof(void*)*outputChannelCount ); + (void **)PaUtil_AllocateZeroInitializedMemory( sizeof(void*)*outputChannelCount ); if( bp->tempOutputBufferPtrs == 0 ) { result = paInsufficientMemory; @@ -341,9 +347,9 @@ PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bp, } bp->hostOutputChannels[0] = (PaUtilChannelDescriptor*) - PaUtil_AllocateMemory( sizeof(PaUtilChannelDescriptor)*outputChannelCount * 2 ); + PaUtil_AllocateZeroInitializedMemory( sizeof(PaUtilChannelDescriptor)*outputChannelCount * 2 ); if( bp->hostOutputChannels[0] == 0 ) - { + { result = paInsufficientMemory; goto error; } @@ -393,7 +399,7 @@ void PaUtil_TerminateBufferProcessor( PaUtilBufferProcessor* bp ) if( bp->hostInputChannels[0] ) PaUtil_FreeMemory( bp->hostInputChannels[0] ); - + if( bp->tempOutputBuffer ) PaUtil_FreeMemory( bp->tempOutputBuffer ); @@ -420,7 +426,7 @@ void PaUtil_ResetBufferProcessor( PaUtilBufferProcessor* bp ) } if( bp->framesInTempOutputBuffer > 0 ) - { + { tempOutputBufferSize = bp->framesPerTempBuffer * bp->bytesPerUserOutputSample * bp->outputChannelCount; memset( bp->tempOutputBuffer, 0, tempOutputBufferSize ); @@ -448,7 +454,7 @@ void PaUtil_SetInputFrameCount( PaUtilBufferProcessor* bp, else bp->hostInputFrameCount[0] = frameCount; } - + void PaUtil_SetNoInput( PaUtilBufferProcessor* bp ) { @@ -462,7 +468,7 @@ void PaUtil_SetInputChannel( PaUtilBufferProcessor* bp, unsigned int channel, void *data, unsigned int stride ) { assert( channel < bp->inputChannelCount ); - + bp->hostInputChannels[0][channel].data = data; bp->hostInputChannels[0][channel].stride = stride; } @@ -496,7 +502,7 @@ void PaUtil_SetNonInterleavedInputChannel( PaUtilBufferProcessor* bp, { assert( channel < bp->inputChannelCount ); assert( !bp->hostInputIsInterleaved ); - + bp->hostInputChannels[0][channel].data = data; bp->hostInputChannels[0][channel].stride = 1; } @@ -532,7 +538,7 @@ void PaUtil_Set2ndInterleavedInputChannels( PaUtilBufferProcessor* bp, assert( firstChannel < bp->inputChannelCount ); assert( firstChannel + channelCount <= bp->inputChannelCount ); assert( bp->hostInputIsInterleaved ); - + for( i=0; i< channelCount; ++i ) { bp->hostInputChannels[1][channel+i].data = p; @@ -541,13 +547,13 @@ void PaUtil_Set2ndInterleavedInputChannels( PaUtilBufferProcessor* bp, } } - + void PaUtil_Set2ndNonInterleavedInputChannel( PaUtilBufferProcessor* bp, unsigned int channel, void *data ) { assert( channel < bp->inputChannelCount ); assert( !bp->hostInputIsInterleaved ); - + bp->hostInputChannels[1][channel].data = data; bp->hostInputChannels[1][channel].stride = 1; } @@ -597,7 +603,7 @@ void PaUtil_SetInterleavedOutputChannels( PaUtilBufferProcessor* bp, assert( firstChannel < bp->outputChannelCount ); assert( firstChannel + channelCount <= bp->outputChannelCount ); assert( bp->hostOutputIsInterleaved ); - + for( i=0; i< channelCount; ++i ) { PaUtil_SetOutputChannel( bp, channel + i, p, channelCount ); @@ -647,7 +653,7 @@ void PaUtil_Set2ndInterleavedOutputChannels( PaUtilBufferProcessor* bp, assert( firstChannel < bp->outputChannelCount ); assert( firstChannel + channelCount <= bp->outputChannelCount ); assert( bp->hostOutputIsInterleaved ); - + for( i=0; i< channelCount; ++i ) { PaUtil_Set2ndOutputChannel( bp, channel + i, p, channelCount ); @@ -655,13 +661,13 @@ void PaUtil_Set2ndInterleavedOutputChannels( PaUtilBufferProcessor* bp, } } - + void PaUtil_Set2ndNonInterleavedOutputChannel( PaUtilBufferProcessor* bp, unsigned int channel, void *data ) { assert( channel < bp->outputChannelCount ); assert( !bp->hostOutputIsInterleaved ); - + PaUtil_Set2ndOutputChannel( bp, channel, data, 1 ); } @@ -673,11 +679,11 @@ void PaUtil_BeginBufferProcessing( PaUtilBufferProcessor* bp, /* the first streamCallback will be called to process samples which are currently in the input buffer before the ones starting at the timeInfo time */ - + bp->timeInfo->inputBufferAdcTime -= bp->framesInTempInputBuffer * bp->samplePeriod; - + /* We just pass through timeInfo->currentTime provided by the caller. This is - not strictly conformant to the word of the spec, since the buffer processor + not strictly conformant to the word of the spec, since the buffer processor might call the callback multiple times, and we never refresh currentTime. */ /* the first streamCallback will be called to generate samples which will be @@ -735,7 +741,7 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp, } else /* there are input channels */ { - + destBytePtr = (unsigned char *)bp->tempInputBuffer; if( bp->userInputIsInterleaved ) @@ -779,7 +785,7 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp, i * bp->bytesPerUserInputSample * frameCount; } } - + userInput = bp->tempInputBufferPtrs; } @@ -795,7 +801,7 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp, } } else - { + { if( skipInputConvert ) { for( i=0; iinputChannelCount; ++i ) @@ -837,7 +843,7 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp, /* process host buffer directly, or use temp buffer if formats differ or host buffer non-interleaved, * or if num channels differs between the host (set in stride) and the user (eg with some Alsa hw:) */ if( bp->userOutputSampleFormatIsEqualToHost && bp->hostOutputIsInterleaved - && bp->outputChannelCount == hostOutputChannels[0].stride ) + && bp->outputChannelCount == hostOutputChannels[0].stride ) { userOutput = hostOutputChannels[0].data; skipOutputConvert = 1; @@ -869,7 +875,7 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp, userOutput = bp->tempOutputBufferPtrs; } } - + *streamCallbackResult = bp->streamCallback( userInput, userOutput, frameCount, bp->timeInfo, bp->callbackStatusFlags, bp->userData ); @@ -884,50 +890,50 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp, bp->timeInfo->outputBufferDacTime += frameCount * bp->samplePeriod; /* convert output data (user -> host) */ - + if( bp->outputChannelCount != 0 && bp->hostOutputChannels[0][0].data ) { if( skipOutputConvert ) - { - for( i=0; ioutputChannelCount; ++i ) - { - /* advance dest ptr for next iteration */ - hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) + - frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample; - } - } - else - { - - srcBytePtr = (unsigned char *)bp->tempOutputBuffer; - - if( bp->userOutputIsInterleaved ) - { - srcSampleStrideSamples = bp->outputChannelCount; - srcChannelStrideBytes = bp->bytesPerUserOutputSample; - } - else /* user output is not interleaved */ - { - srcSampleStrideSamples = 1; - srcChannelStrideBytes = frameCount * bp->bytesPerUserOutputSample; - } - - for( i=0; ioutputChannelCount; ++i ) - { - bp->outputConverter( hostOutputChannels[i].data, - hostOutputChannels[i].stride, - srcBytePtr, srcSampleStrideSamples, - frameCount, &bp->ditherGenerator ); - - srcBytePtr += srcChannelStrideBytes; /* skip to next source channel */ - - /* advance dest ptr for next iteration */ - hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) + - frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample; - } - } + { + for( i=0; ioutputChannelCount; ++i ) + { + /* advance dest ptr for next iteration */ + hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) + + frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample; + } + } + else + { + + srcBytePtr = (unsigned char *)bp->tempOutputBuffer; + + if( bp->userOutputIsInterleaved ) + { + srcSampleStrideSamples = bp->outputChannelCount; + srcChannelStrideBytes = bp->bytesPerUserOutputSample; + } + else /* user output is not interleaved */ + { + srcSampleStrideSamples = 1; + srcChannelStrideBytes = frameCount * bp->bytesPerUserOutputSample; + } + + for( i=0; ioutputChannelCount; ++i ) + { + bp->outputConverter( hostOutputChannels[i].data, + hostOutputChannels[i].stride, + srcBytePtr, srcSampleStrideSamples, + frameCount, &bp->ditherGenerator ); + + srcBytePtr += srcChannelStrideBytes; /* skip to next source channel */ + + /* advance dest ptr for next iteration */ + hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) + + frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample; + } + } } - + framesProcessed += frameCount; framesToGo -= frameCount; @@ -982,7 +988,7 @@ static unsigned long AdaptingInputOnlyProcess( PaUtilBufferProcessor *bp, unsigned long frameCount; unsigned long framesToGo = framesToProcess; unsigned long framesProcessed = 0; - + userOutput = 0; do @@ -998,7 +1004,7 @@ static unsigned long AdaptingInputOnlyProcess( PaUtilBufferProcessor *bp, destBytePtr = ((unsigned char*)bp->tempInputBuffer) + bp->bytesPerUserInputSample * bp->inputChannelCount * bp->framesInTempInputBuffer; - + destSampleStrideSamples = bp->inputChannelCount; destChannelStrideBytes = bp->bytesPerUserInputSample; @@ -1018,7 +1024,7 @@ static unsigned long AdaptingInputOnlyProcess( PaUtilBufferProcessor *bp, bp->tempInputBufferPtrs[i] = ((unsigned char*)bp->tempInputBuffer) + i * bp->bytesPerUserInputSample * bp->framesPerUserBuffer; } - + userInput = bp->tempInputBufferPtrs; } @@ -1058,7 +1064,7 @@ static unsigned long AdaptingInputOnlyProcess( PaUtilBufferProcessor *bp, bp->timeInfo->inputBufferAdcTime += bp->framesPerUserBuffer * bp->samplePeriod; } - + bp->framesInTempInputBuffer = 0; } @@ -1113,7 +1119,7 @@ static unsigned long AdaptingOutputOnlyProcess( PaUtilBufferProcessor *bp, } bp->timeInfo->inputBufferAdcTime = 0; - + *streamCallbackResult = bp->streamCallback( userInput, userOutput, bp->framesPerUserBuffer, bp->timeInfo, bp->callbackStatusFlags, bp->userData ); @@ -1150,7 +1156,7 @@ static unsigned long AdaptingOutputOnlyProcess( PaUtilBufferProcessor *bp, srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) + bp->bytesPerUserOutputSample * (bp->framesPerUserBuffer - bp->framesInTempOutputBuffer); - + srcSampleStrideSamples = 1; srcChannelStrideBytes = bp->framesPerUserBuffer * bp->bytesPerUserOutputSample; } @@ -1191,9 +1197,9 @@ static unsigned long AdaptingOutputOnlyProcess( PaUtilBufferProcessor *bp, frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample; } } - + framesProcessed += frameCount; - + framesToGo -= frameCount; }while( framesToGo > 0 ); @@ -1202,8 +1208,8 @@ static unsigned long AdaptingOutputOnlyProcess( PaUtilBufferProcessor *bp, } /* CopyTempOutputBuffersToHostOutputBuffers is called from AdaptingProcess to copy frames from - tempOutputBuffer to hostOutputChannels. This includes data conversion - and interleaving. + tempOutputBuffer to hostOutputChannels. This includes data conversion + and interleaving. */ static void CopyTempOutputBuffersToHostOutputBuffers( PaUtilBufferProcessor *bp) { @@ -1215,65 +1221,65 @@ static void CopyTempOutputBuffersToHostOutputBuffers( PaUtilBufferProcessor *bp) unsigned int srcChannelStrideBytes; /* stride from one channel to the next, in bytes */ unsigned int i; - /* copy frames from user to host output buffers */ - while( bp->framesInTempOutputBuffer > 0 && - ((bp->hostOutputFrameCount[0] + bp->hostOutputFrameCount[1]) > 0) ) - { - maxFramesToCopy = bp->framesInTempOutputBuffer; - - /* select the output buffer set (1st or 2nd) */ - if( bp->hostOutputFrameCount[0] > 0 ) - { - hostOutputChannels = bp->hostOutputChannels[0]; - frameCount = PA_MIN_( bp->hostOutputFrameCount[0], maxFramesToCopy ); - } - else - { - hostOutputChannels = bp->hostOutputChannels[1]; - frameCount = PA_MIN_( bp->hostOutputFrameCount[1], maxFramesToCopy ); - } - - if( bp->userOutputIsInterleaved ) - { - srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) + - bp->bytesPerUserOutputSample * bp->outputChannelCount * - (bp->framesPerUserBuffer - bp->framesInTempOutputBuffer); - - srcSampleStrideSamples = bp->outputChannelCount; - srcChannelStrideBytes = bp->bytesPerUserOutputSample; - } - else /* user output is not interleaved */ - { - srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) + - bp->bytesPerUserOutputSample * - (bp->framesPerUserBuffer - bp->framesInTempOutputBuffer); - - srcSampleStrideSamples = 1; - srcChannelStrideBytes = bp->framesPerUserBuffer * bp->bytesPerUserOutputSample; - } - - for( i=0; ioutputChannelCount; ++i ) - { - assert( hostOutputChannels[i].data != NULL ); - bp->outputConverter( hostOutputChannels[i].data, - hostOutputChannels[i].stride, - srcBytePtr, srcSampleStrideSamples, - frameCount, &bp->ditherGenerator ); - - srcBytePtr += srcChannelStrideBytes; /* skip to next source channel */ - - /* advance dest ptr for next iteration */ - hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) + - frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample; - } - - if( bp->hostOutputFrameCount[0] > 0 ) - bp->hostOutputFrameCount[0] -= frameCount; - else - bp->hostOutputFrameCount[1] -= frameCount; - - bp->framesInTempOutputBuffer -= frameCount; - } + /* copy frames from user to host output buffers */ + while( bp->framesInTempOutputBuffer > 0 && + ((bp->hostOutputFrameCount[0] + bp->hostOutputFrameCount[1]) > 0) ) + { + maxFramesToCopy = bp->framesInTempOutputBuffer; + + /* select the output buffer set (1st or 2nd) */ + if( bp->hostOutputFrameCount[0] > 0 ) + { + hostOutputChannels = bp->hostOutputChannels[0]; + frameCount = PA_MIN_( bp->hostOutputFrameCount[0], maxFramesToCopy ); + } + else + { + hostOutputChannels = bp->hostOutputChannels[1]; + frameCount = PA_MIN_( bp->hostOutputFrameCount[1], maxFramesToCopy ); + } + + if( bp->userOutputIsInterleaved ) + { + srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) + + bp->bytesPerUserOutputSample * bp->outputChannelCount * + (bp->framesPerUserBuffer - bp->framesInTempOutputBuffer); + + srcSampleStrideSamples = bp->outputChannelCount; + srcChannelStrideBytes = bp->bytesPerUserOutputSample; + } + else /* user output is not interleaved */ + { + srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) + + bp->bytesPerUserOutputSample * + (bp->framesPerUserBuffer - bp->framesInTempOutputBuffer); + + srcSampleStrideSamples = 1; + srcChannelStrideBytes = bp->framesPerUserBuffer * bp->bytesPerUserOutputSample; + } + + for( i=0; ioutputChannelCount; ++i ) + { + assert( hostOutputChannels[i].data != NULL ); + bp->outputConverter( hostOutputChannels[i].data, + hostOutputChannels[i].stride, + srcBytePtr, srcSampleStrideSamples, + frameCount, &bp->ditherGenerator ); + + srcBytePtr += srcChannelStrideBytes; /* skip to next source channel */ + + /* advance dest ptr for next iteration */ + hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) + + frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample; + } + + if( bp->hostOutputFrameCount[0] > 0 ) + bp->hostOutputFrameCount[0] -= frameCount; + else + bp->hostOutputFrameCount[1] -= frameCount; + + bp->framesInTempOutputBuffer -= frameCount; + } } /* @@ -1300,7 +1306,7 @@ static unsigned long AdaptingProcess( PaUtilBufferProcessor *bp, unsigned int destSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */ unsigned int destChannelStrideBytes; /* stride from one channel to the next, in bytes */ unsigned int i, j; - + framesAvailable = bp->hostInputFrameCount[0] + bp->hostInputFrameCount[1];/* this is assumed to be the same as the output buffer's frame count */ @@ -1310,9 +1316,9 @@ static unsigned long AdaptingProcess( PaUtilBufferProcessor *bp, endProcessingMinFrameCount = (bp->framesPerUserBuffer - 1); /* Fill host output with remaining frames in user output (tempOutputBuffer) */ - CopyTempOutputBuffersToHostOutputBuffers( bp ); + CopyTempOutputBuffersToHostOutputBuffers( bp ); - while( framesAvailable > endProcessingMinFrameCount ) + while( framesAvailable > endProcessingMinFrameCount ) { if( bp->framesInTempOutputBuffer == 0 && *streamCallbackResult != paContinue ) @@ -1326,7 +1332,7 @@ static unsigned long AdaptingProcess( PaUtilBufferProcessor *bp, if( frameCount > 0 ) { hostOutputChannels = bp->hostOutputChannels[i]; - + for( j=0; joutputChannelCount; ++j ) { bp->outputZeroer( hostOutputChannels[j].data, @@ -1340,7 +1346,7 @@ static unsigned long AdaptingProcess( PaUtilBufferProcessor *bp, bp->hostOutputFrameCount[i] = 0; } } - } + } /* copy frames from host to user input buffers */ @@ -1398,7 +1404,7 @@ static unsigned long AdaptingProcess( PaUtilBufferProcessor *bp, bp->hostInputFrameCount[0] -= frameCount; else bp->hostInputFrameCount[1] -= frameCount; - + bp->framesInTempInputBuffer += frameCount; /* update framesAvailable and framesProcessed based on input consumed @@ -1470,13 +1476,13 @@ static unsigned long AdaptingProcess( PaUtilBufferProcessor *bp, } } - /* copy frames from user (tempOutputBuffer) to host output buffers (hostOutputChannels) + /* copy frames from user (tempOutputBuffer) to host output buffers (hostOutputChannels) Means to process the user output provided by the callback. Has to be called after each callback. */ - CopyTempOutputBuffersToHostOutputBuffers( bp ); + CopyTempOutputBuffersToHostOutputBuffers( bp ); } - + return framesProcessed; } @@ -1485,7 +1491,7 @@ unsigned long PaUtil_EndBufferProcessing( PaUtilBufferProcessor* bp, int *stream { unsigned long framesToProcess, framesToGo; unsigned long framesProcessed = 0; - + if( bp->inputChannelCount != 0 && bp->outputChannelCount != 0 && bp->hostInputChannels[0][0].data /* input was supplied (see PaUtil_SetNoInput) */ && bp->hostOutputChannels[0][0].data /* output was supplied (see PaUtil_SetNoOutput) */ ) @@ -1560,17 +1566,17 @@ unsigned long PaUtil_EndBufferProcessing( PaUtilBufferProcessor* bp, int *stream *hostOutputFrameCount ); assert( framesToProcess != 0 ); - + framesProcessedThisIteration = NonAdaptingProcess( bp, streamCallbackResult, hostInputChannels, hostOutputChannels, - framesToProcess ); + framesToProcess ); *hostInputFrameCount -= framesProcessedThisIteration; *hostOutputFrameCount -= framesProcessedThisIteration; framesProcessed += framesProcessedThisIteration; framesToGo -= framesProcessedThisIteration; - + }while( framesToGo > 0 ); } else @@ -1587,7 +1593,7 @@ unsigned long PaUtil_EndBufferProcessing( PaUtilBufferProcessor* bp, int *stream framesToProcess ); /* process second buffer if provided */ - + framesToProcess = (bp->inputChannelCount != 0) ? bp->hostInputFrameCount[1] : bp->hostOutputFrameCount[1]; @@ -1605,7 +1611,7 @@ unsigned long PaUtil_EndBufferProcessing( PaUtilBufferProcessor* bp, int *stream if( bp->inputChannelCount != 0 && bp->outputChannelCount != 0 ) { /* full duplex */ - + if( bp->hostBufferSizeMode == paUtilVariableHostBufferSizePartialUsageAllowed ) { framesProcessed = AdaptingProcess( bp, streamCallbackResult, @@ -1656,7 +1662,7 @@ unsigned long PaUtil_EndBufferProcessing( PaUtilBufferProcessor* bp, int *stream int PaUtil_IsBufferProcessorOutputEmpty( PaUtilBufferProcessor* bp ) { return (bp->framesInTempOutputBuffer) ? 0 : 1; -} +} unsigned long PaUtil_CopyInput( PaUtilBufferProcessor* bp, @@ -1676,7 +1682,7 @@ unsigned long PaUtil_CopyInput( PaUtilBufferProcessor* bp, if( bp->userInputIsInterleaved ) { destBytePtr = (unsigned char*)*buffer; - + destSampleStrideSamples = bp->inputChannelCount; destChannelStrideBytes = bp->bytesPerUserInputSample; @@ -1701,11 +1707,11 @@ unsigned long PaUtil_CopyInput( PaUtilBufferProcessor* bp, else { /* user input is not interleaved */ - + nonInterleavedDestPtrs = (void**)*buffer; destSampleStrideSamples = 1; - + for( i=0; iinputChannelCount; ++i ) { destBytePtr = (unsigned char*)nonInterleavedDestPtrs[i]; @@ -1718,7 +1724,7 @@ unsigned long PaUtil_CopyInput( PaUtilBufferProcessor* bp, /* advance callers dest pointer (nonInterleavedDestPtrs[i]) */ destBytePtr += bp->bytesPerUserInputSample * framesToCopy; nonInterleavedDestPtrs[i] = destBytePtr; - + /* advance source ptr for next iteration */ hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) + framesToCopy * hostInputChannels[i].stride * bp->bytesPerHostInputSample; @@ -1726,7 +1732,7 @@ unsigned long PaUtil_CopyInput( PaUtilBufferProcessor* bp, } bp->hostInputFrameCount[0] -= framesToCopy; - + return framesToCopy; } @@ -1747,7 +1753,7 @@ unsigned long PaUtil_CopyOutput( PaUtilBufferProcessor* bp, if( bp->userOutputIsInterleaved ) { srcBytePtr = (unsigned char*)*buffer; - + srcSampleStrideSamples = bp->outputChannelCount; srcChannelStrideBytes = bp->bytesPerUserOutputSample; @@ -1773,15 +1779,15 @@ unsigned long PaUtil_CopyOutput( PaUtilBufferProcessor* bp, else { /* user output is not interleaved */ - + nonInterleavedSrcPtrs = (void**)*buffer; srcSampleStrideSamples = 1; - + for( i=0; ioutputChannelCount; ++i ) { srcBytePtr = (unsigned char*)nonInterleavedSrcPtrs[i]; - + bp->outputConverter( hostOutputChannels[i].data, hostOutputChannels[i].stride, srcBytePtr, srcSampleStrideSamples, @@ -1791,7 +1797,7 @@ unsigned long PaUtil_CopyOutput( PaUtilBufferProcessor* bp, /* advance callers source pointer (nonInterleavedSrcPtrs[i]) */ srcBytePtr += bp->bytesPerUserOutputSample * framesToCopy; nonInterleavedSrcPtrs[i] = srcBytePtr; - + /* advance dest ptr for next iteration */ hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) + framesToCopy * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample; @@ -1799,7 +1805,7 @@ unsigned long PaUtil_CopyOutput( PaUtilBufferProcessor* bp, } bp->hostOutputFrameCount[0] += framesToCopy; - + return framesToCopy; } @@ -1826,6 +1832,6 @@ unsigned long PaUtil_ZeroOutput( PaUtilBufferProcessor* bp, unsigned long frameC } bp->hostOutputFrameCount[0] += framesToZero; - + return framesToZero; } diff --git a/3rdparty/portaudio/src/common/pa_process.h b/3rdparty/portaudio/src/common/pa_process.h index 37b91d7218e..444bdf54513 100644 --- a/3rdparty/portaudio/src/common/pa_process.h +++ b/3rdparty/portaudio/src/common/pa_process.h @@ -28,16 +28,16 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * 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 @@ -72,13 +72,13 @@ The following sections provide an overview of how to use the buffer processor. Interested readers are advised to consult the host API implementations for examples of buffer processor usage. - +

Initialization, resetting and termination

When a stream is opened, the buffer processor should be initialized using PaUtil_InitializeBufferProcessor. This function initializes internal state - and allocates temporary buffers as neccesary according to the supplied + and allocates temporary buffers as necessary according to the supplied configuration parameters. Some of the parameters correspond to those requested by the user in their call to Pa_OpenStream(), others reflect the requirements of the host API implementation - they indicate host buffer sizes, formats, @@ -92,7 +92,7 @@ When the buffer processor is no longer used call PaUtil_TerminateBufferProcessor. - +

Using the buffer processor for a callback stream

The buffer processor's role in a callback stream is to take host input buffers @@ -119,7 +119,7 @@ PaUtil_SetInterleavedInputChannels, PaUtil_SetNonInterleavedInputChannel. Which function you call will depend on whether the host buffer(s) are interleaved or not. - - If the available host data is split accross two buffers (for example a + - If the available host data is split across two buffers (for example a data range at the end of a circular buffer and another range at the beginning of the circular buffer), also call PaUtil_Set2ndInputFrameCount, PaUtil_Set2ndInputChannel, @@ -134,7 +134,7 @@ PaUtil_SetInterleavedOutputChannels, PaUtil_SetNonInterleavedOutputChannel. Which function you call will depend on whether the host buffer(s) are interleaved or not. - - If the available host output buffer space is split accross two buffers + - If the available host output buffer space is split across two buffers (for example a data range at the end of a circular buffer and another range at the beginning of the circular buffer), call PaUtil_Set2ndOutputFrameCount, PaUtil_Set2ndOutputChannel, @@ -176,7 +176,7 @@ host buffer(s), so the above steps need to be repeated until the user buffer(s) are full. - + To copy data to the host output buffer from the user buffers(s) supplied to Pa_WriteStream use the following calling sequence. @@ -192,7 +192,7 @@ -# Call PaUtil_CopyOutput with the user buffer pointer (or a copy of the array of buffer pointers for a non-interleaved stream) passed to Pa_WriteStream, along with the number of frames in the user buffer(s). - Be careful to pass a copy of the user buffer pointers to + Be careful to pass a copy of the user buffer pointers to PaUtil_CopyOutput because PaUtil_CopyOutput advances the pointers to the start of the next region to copy. - PaUtil_CopyOutput will not copy more data than fits in the host buffer(s), @@ -237,7 +237,7 @@ typedef enum { }PaUtilHostBufferSizeMode; -/** @brief An auxilliary data structure used internally by the buffer processor +/** @brief An auxiliary data structure used internally by the buffer processor to represent host input and output buffers. */ typedef struct PaUtilChannelDescriptor{ void *data; @@ -266,7 +266,7 @@ typedef struct { int userInputIsInterleaved; PaUtilConverter *inputConverter; PaUtilZeroer *inputZeroer; - + unsigned int outputChannelCount; unsigned int bytesPerHostOutputSample; unsigned int bytesPerUserOutputSample; @@ -327,7 +327,7 @@ typedef struct { @param userInputSampleFormat Format of user input samples, as passed to Pa_OpenStream. This parameter is ignored for ouput-only streams. - + @param hostInputSampleFormat Format of host input samples. This parameter is ignored for output-only streams. See note about host buffer interleave below. @@ -336,17 +336,17 @@ typedef struct { @param userOutputSampleFormat Format of user output samples, as passed to Pa_OpenStream. This parameter is ignored for input-only streams. - + @param hostOutputSampleFormat Format of host output samples. This parameter is ignored for input-only streams. See note about host buffer interleave below. @param sampleRate Sample rate of the stream. The more accurate this is the better - it is used for updating time stamps when adapting buffers. - + @param streamFlags Stream flags as passed to Pa_OpenStream, this parameter is used for selecting special sample conversion options such as clipping and dithering. - + @param framesPerUserBuffer Number of frames per user buffer, as requested by the framesPerBuffer parameter to Pa_OpenStream. This parameter may be zero to indicate that the user will accept any (and varying) buffer sizes. @@ -359,11 +359,11 @@ typedef struct { @param hostBufferSizeMode A mode flag indicating the size variability of host buffers that will be passed to the buffer processor. See PaUtilHostBufferSizeMode for further details. - + @param streamCallback The user stream callback passed to Pa_OpenStream. @param userData The user data field passed to Pa_OpenStream. - + @note The interleave flag is ignored for host buffer formats. Host interleave is determined by the use of different SetInput and SetOutput functions. @@ -371,7 +371,7 @@ typedef struct { @return An error code indicating whether the initialization was successful. If the error code is not PaNoError, the buffer processor was not initialized and should not be used. - + @see Pa_OpenStream, PaUtilHostBufferSizeMode, PaUtil_TerminateBufferProcessor */ PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bufferProcessor, @@ -389,7 +389,7 @@ PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bufferProcessor /** Terminate a buffer processor's representation. Deallocates any temporary buffers allocated by PaUtil_InitializeBufferProcessor. - + @param bufferProcessor The buffer processor structure to terminate. @see PaUtil_InitializeBufferProcessor. @@ -434,7 +434,7 @@ unsigned long PaUtil_GetBufferProcessorOutputLatencyFrames( PaUtilBufferProcesso Functions to set host input and output buffers, used by both callback streams and blocking read/write streams. */ -/*@{*/ +/*@{*/ /** Set the number of frames in the input host buffer(s) specified by the @@ -451,11 +451,11 @@ unsigned long PaUtil_GetBufferProcessorOutputLatencyFrames( PaUtilBufferProcesso void PaUtil_SetInputFrameCount( PaUtilBufferProcessor* bufferProcessor, unsigned long frameCount ); - -/** Indicate that no input is avalable. This function should be used when + +/** Indicate that no input is available. This function should be used when priming the output of a full-duplex stream opened with the paPrimeOutputBuffersUsingStreamCallback flag. Note that it is not necessary - to call this or any othe PaUtil_Set*Input* functions for ouput-only streams. + to call this or any other PaUtil_Set*Input* functions for ouput-only streams. @param bufferProcessor The buffer processor. */ @@ -524,7 +524,7 @@ void PaUtil_Set2ndInterleavedInputChannels( PaUtilBufferProcessor* bufferProcess void PaUtil_Set2ndNonInterleavedInputChannel( PaUtilBufferProcessor* bufferProcessor, unsigned int channel, void *data ); - + /** Set the number of frames in the output host buffer(s) specified by the PaUtil_Set*OutputChannel functions. @@ -574,7 +574,7 @@ void PaUtil_SetOutputChannel( PaUtilBufferProcessor* bufferProcessor, void PaUtil_SetInterleavedOutputChannels( PaUtilBufferProcessor* bufferProcessor, unsigned int firstChannel, void *data, unsigned int channelCount ); - + /** Provide the buffer processor with a pointer to one non-interleaved host output channel. @@ -632,12 +632,12 @@ void PaUtil_Set2ndNonInterleavedOutputChannel( PaUtilBufferProcessor* bufferProc void PaUtil_BeginBufferProcessing( PaUtilBufferProcessor* bufferProcessor, PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags callbackStatusFlags ); - + /** Finish processing a host buffer (or a pair of host buffers in the full-duplex case) for a callback stream. @param bufferProcessor The buffer processor. - + @param callbackResult On input, indicates a previous callback result, and on exit, the result of the user stream callback, if it is called. On entry callbackResult should contain one of { paContinue, paComplete, or @@ -648,11 +648,11 @@ void PaUtil_BeginBufferProcessing( PaUtilBufferProcessor* bufferProcessor, If the stream callback is called its result is stored in *callbackResult. If the stream callback returns paComplete or paAbort, all output buffers will be - full of valid data - some of which may be zeros to acount for data that + full of valid data - some of which may be zeros to account for data that wasn't generated by the terminating callback. @return The number of frames processed. This usually corresponds to the - number of frames specified by the PaUtil_Set*FrameCount functions, exept in + number of frames specified by the PaUtil_Set*FrameCount functions, except in the paUtilVariableHostBufferSizePartialUsageAllowed buffer size mode when a smaller value may be returned. */ @@ -660,13 +660,13 @@ unsigned long PaUtil_EndBufferProcessing( PaUtilBufferProcessor* bufferProcessor int *callbackResult ); -/** Determine whether any callback generated output remains in the bufffer +/** Determine whether any callback generated output remains in the buffer processor's internal buffers. This method may be used to determine when to continue calling PaUtil_EndBufferProcessing() after the callback has returned a callbackResult of paComplete. @param bufferProcessor The buffer processor. - + @return Returns non-zero when callback generated output remains in the internal buffer and zero (0) when there internal buffer contains no callback generated data. @@ -738,7 +738,7 @@ unsigned long PaUtil_CopyOutput( PaUtilBufferProcessor* bufferProcessor, @param bufferProcessor The buffer processor. @param frameCount The maximum number of frames to zero. - + @return The number of frames zeroed. */ unsigned long PaUtil_ZeroOutput( PaUtilBufferProcessor* bufferProcessor, diff --git a/3rdparty/portaudio/src/common/pa_ringbuffer.c b/3rdparty/portaudio/src/common/pa_ringbuffer.c index 93b3e430a51..b978d54f195 100644 --- a/3rdparty/portaudio/src/common/pa_ringbuffer.c +++ b/3rdparty/portaudio/src/common/pa_ringbuffer.c @@ -7,7 +7,7 @@ * modified for SMP safety on Mac OS X by Bjorn Roche * modified for SMP safety on Linux by Leland Lucius * also, allowed for const where possible - * modified for multiple-byte-sized data elements by Sven Fischer + * modified for multiple-byte-sized data elements by Sven Fischer * * Note that this is safe only for a single-thread reader and a * single-thread writer. @@ -37,13 +37,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -138,7 +138,7 @@ ring_buffer_size_t PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, rin */ ring_buffer_size_t PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount ) { - /* ensure that previous writes are seen before we update the write index + /* ensure that previous writes are seen before we update the write index (write after write) */ PaUtil_WriteMemoryBarrier(); @@ -176,7 +176,7 @@ ring_buffer_size_t PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, ring *dataPtr2 = NULL; *sizePtr2 = 0; } - + if( available ) PaUtil_ReadMemoryBarrier(); /* (read-after-read) => read barrier */ @@ -186,7 +186,7 @@ ring_buffer_size_t PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, ring */ ring_buffer_size_t PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, ring_buffer_size_t elementCount ) { - /* ensure that previous reads (copies out of the ring buffer) are always completed before updating (writing) the read index. + /* ensure that previous reads (copies out of the ring buffer) are always completed before updating (writing) the read index. (write-after-read) => full barrier */ PaUtil_FullMemoryBarrier(); diff --git a/3rdparty/portaudio/src/common/pa_ringbuffer.h b/3rdparty/portaudio/src/common/pa_ringbuffer.h index 9edba0dd657..400aaac659b 100644 --- a/3rdparty/portaudio/src/common/pa_ringbuffer.h +++ b/3rdparty/portaudio/src/common/pa_ringbuffer.h @@ -8,7 +8,7 @@ * Author: Phil Burk, http://www.softsynth.com * modified for SMP safety on OS X by Bjorn Roche. * also allowed for const where possible. - * modified for multiple-byte-sized data elements by Sven Fischer + * modified for multiple-byte-sized data elements by Sven Fischer * * Note that this is safe only for a single-thread reader * and a single-thread writer. @@ -38,13 +38,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -58,15 +58,15 @@ a single reader and a single writer (ie. one thread or callback writes to the ring buffer, another thread or callback reads from it). - The PaUtilRingBuffer structure manages a ring buffer containing N - elements, where N must be a power of two. An element may be any size + The PaUtilRingBuffer structure manages a ring buffer containing N + elements, where N must be a power of two. An element may be any size (specified in bytes). - The memory area used to store the buffer elements must be allocated by + The memory area used to store the buffer elements must be allocated by the client prior to calling PaUtil_InitializeRingBuffer() and must outlive the use of the ring buffer. - - @note The ring buffer functions are not normally exposed in the PortAudio libraries. + + @note The ring buffer functions are not normally exposed in the PortAudio libraries. If you want to call them then you will need to add pa_ringbuffer.c to your application source code. */ diff --git a/3rdparty/portaudio/src/common/pa_stream.c b/3rdparty/portaudio/src/common/pa_stream.c index 03a0ee6ee32..ffbf5303237 100644 --- a/3rdparty/portaudio/src/common/pa_stream.c +++ b/3rdparty/portaudio/src/common/pa_stream.c @@ -27,13 +27,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ diff --git a/3rdparty/portaudio/src/common/pa_stream.h b/3rdparty/portaudio/src/common/pa_stream.h index 678e2ad5ea0..4afda399b1e 100644 --- a/3rdparty/portaudio/src/common/pa_stream.h +++ b/3rdparty/portaudio/src/common/pa_stream.h @@ -29,13 +29,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -164,7 +164,7 @@ void PaUtil_InitializeStreamRepresentation( PaUtilStreamInterface *streamInterface, PaStreamCallback *streamCallback, void *userData ); - + /** Clean up a PaUtilStreamRepresentation structure previously initialized by a call to PaUtil_InitializeStreamRepresentation. @@ -198,7 +198,7 @@ PaError PaUtil_ValidateStreamPointer( PaStream *stream ); PA_STREAM_REP( (stream) )->streamInterface - + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/3rdparty/portaudio/src/common/pa_trace.c b/3rdparty/portaudio/src/common/pa_trace.c index 818abffbeec..7fd589ee4c5 100644 --- a/3rdparty/portaudio/src/common/pa_trace.c +++ b/3rdparty/portaudio/src/common/pa_trace.c @@ -27,13 +27,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -120,7 +120,7 @@ static const unsigned kMagik = 0xcafebabe; int PaUtil_InitializeHighSpeedLog( LogHandle* phLog, unsigned maxSizeInBytes ) { - PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)PaUtil_AllocateMemory(sizeof(PaHighPerformanceLog)); + PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)PaUtil_AllocateZeroInitializedMemory(sizeof(PaHighPerformanceLog)); if (pLog == 0) { return paInsufficientMemory; @@ -128,7 +128,7 @@ int PaUtil_InitializeHighSpeedLog( LogHandle* phLog, unsigned maxSizeInBytes ) assert(phLog != 0); *phLog = pLog; - pLog->data = (char*)PaUtil_AllocateMemory(maxSizeInBytes); + pLog->data = (char*)PaUtil_AllocateZeroInitializedMemory(maxSizeInBytes); if (pLog->data == 0) { PaUtil_FreeMemory(pLog); @@ -233,6 +233,6 @@ void PaUtil_DiscardHighSpeedLog( LogHandle hLog ) */ int PaUtil_TraceStubToSatisfyLinker(void) { - return 0; + return 0; } #endif /* TRACE_REALTIME_EVENTS */ diff --git a/3rdparty/portaudio/src/common/pa_trace.h b/3rdparty/portaudio/src/common/pa_trace.h index 6dfaeb79ec4..7827766bc7f 100644 --- a/3rdparty/portaudio/src/common/pa_trace.h +++ b/3rdparty/portaudio/src/common/pa_trace.h @@ -29,13 +29,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -45,8 +45,8 @@ @brief Real-time safe event trace logging facility for debugging. Allows data to be logged to a fixed size trace buffer in a real-time - execution context (such as at interrupt time). Each log entry consists - of a message comprising a string pointer and an int. The trace buffer + execution context (such as at interrupt time). Each log entry consists + of a message comprising a string pointer and an int. The trace buffer may be dumped to stdout later. This facility is only active if PA_TRACE_REALTIME_EVENTS is set to 1, @@ -57,8 +57,8 @@ @fn PaUtil_AddTraceMessage @brief Add a message to the trace buffer. A message consists of string and an int. - @param msg The string pointer must remain valid until PaUtil_DumpTraceMessages - is called. As a result, usually only string literals should be passed as + @param msg The string pointer must remain valid until PaUtil_DumpTraceMessages + is called. As a result, usually only string literals should be passed as the msg parameter. @fn PaUtil_DumpTraceMessages @@ -70,7 +70,7 @@ #endif #ifndef PA_MAX_TRACE_RECORDS -#define PA_MAX_TRACE_RECORDS (2048) /**< Maximum number of records stored in trace buffer */ +#define PA_MAX_TRACE_RECORDS (2048) /**< Maximum number of records stored in trace buffer */ #endif #ifdef __cplusplus diff --git a/3rdparty/portaudio/src/common/pa_types.h b/3rdparty/portaudio/src/common/pa_types.h index 5b647d641ea..f628783adf8 100644 --- a/3rdparty/portaudio/src/common/pa_types.h +++ b/3rdparty/portaudio/src/common/pa_types.h @@ -1,7 +1,7 @@ #ifndef PA_TYPES_H #define PA_TYPES_H -/* +/* * Portable Audio I/O Library * integer type definitions * @@ -29,13 +29,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ diff --git a/3rdparty/portaudio/src/common/pa_util.h b/3rdparty/portaudio/src/common/pa_util.h index ad5dac52879..fb4b329663c 100644 --- a/3rdparty/portaudio/src/common/pa_util.h +++ b/3rdparty/portaudio/src/common/pa_util.h @@ -29,13 +29,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -51,6 +51,13 @@ #include "portaudio.h" +/** Preprocessor Utilities +*/ + +#define PA_STRINGIZE_HELPER(x) #x +#define PA_STRINGIZE(x) PA_STRINGIZE_HELPER(x) + + #ifdef __cplusplus extern "C" { @@ -65,7 +72,7 @@ struct PaUtilHostApiRepresentation; host api specific extension functions which aren't passed a rep pointer by pa_front.c. - @param hostApi A pointer to a host API represenation pointer. Apon success + @param hostApi A pointer to a host API representation pointer. Upon success this will receive the requested representation pointer. @param type A valid host API type identifier. @@ -79,7 +86,7 @@ PaError PaUtil_GetHostApiRepresentation( struct PaUtilHostApiRepresentation **ho /** Convert a PortAudio device index into a host API specific device index. - @param hostApiDevice Pointer to a device index, on success this will recieve the + @param hostApiDevice Pointer to a device index, on success this will receive the converted device index value. @param device The PortAudio device index to convert. @param hostApi The host api which the index should be converted for. @@ -112,16 +119,19 @@ void PaUtil_SetLastHostErrorInfo( PaHostApiTypeId hostApiType, long errorCode, const char *errorText ); - + /* the following functions are implemented in a platform platform specific .c file */ -/** Allocate size bytes, guaranteed to be aligned to a FIXME byte boundary */ -void *PaUtil_AllocateMemory( long size ); +/** Allocate size bytes of zero-initialized memory. +Guaranteed to be aligned to a FIXME byte boundary. +*/ +void *PaUtil_AllocateZeroInitializedMemory( long size ); -/** Realease block if non-NULL. block may be NULL */ +/** Release block allocated by PaUtil_AllocateZeroInitializedMemory() +if block is non-NULL. block may be NULL */ void PaUtil_FreeMemory( void *block ); diff --git a/3rdparty/portaudio/src/hostapi/alsa/pa_linux_alsa.c b/3rdparty/portaudio/src/hostapi/alsa/pa_linux_alsa.c index 73fceb3be6c..ccbd88bb644 100644 --- a/3rdparty/portaudio/src/hostapi/alsa/pa_linux_alsa.c +++ b/3rdparty/portaudio/src/hostapi/alsa/pa_linux_alsa.c @@ -220,8 +220,10 @@ _PA_DEFINE_FUNC(snd_config_update_free_global); _PA_DEFINE_FUNC(snd_pcm_status); _PA_DEFINE_FUNC(snd_pcm_status_sizeof); _PA_DEFINE_FUNC(snd_pcm_status_get_tstamp); +_PA_DEFINE_FUNC(snd_pcm_status_get_htstamp); _PA_DEFINE_FUNC(snd_pcm_status_get_state); _PA_DEFINE_FUNC(snd_pcm_status_get_trigger_tstamp); +_PA_DEFINE_FUNC(snd_pcm_status_get_trigger_htstamp); _PA_DEFINE_FUNC(snd_pcm_status_get_delay); #define alsa_snd_pcm_status_alloca(ptr) __alsa_snd_alloca(ptr, snd_pcm_status) @@ -239,7 +241,7 @@ _PA_DEFINE_FUNC(snd_output_stdio_attach); /* Redefine 'PA_ALSA_PATHNAME' to a different Alsa library name if desired. */ #ifndef PA_ALSA_PATHNAME - #define PA_ALSA_PATHNAME "libasound.so" + #define PA_ALSA_PATHNAME "libasound.so.2" #endif static const char *g_AlsaLibName = PA_ALSA_PATHNAME; @@ -323,8 +325,10 @@ int _PA_LOCAL_IMPL(snd_pcm_hw_params_get_buffer_size_max) (const snd_pcm_hw_para snd_pcm_uframes_t pmax = 0; unsigned int pcnt = 0; + dir = 0; if(( ret = _PA_LOCAL_IMPL(snd_pcm_hw_params_get_period_size_max)(params, &pmax, &dir) ) < 0 ) return ret; + dir = 0; if(( ret = _PA_LOCAL_IMPL(snd_pcm_hw_params_get_periods_max)(params, &pcnt, &dir) ) < 0 ) return ret; @@ -497,8 +501,10 @@ static int PaAlsa_LoadLibrary() _PA_LOAD_FUNC(snd_pcm_status); _PA_LOAD_FUNC(snd_pcm_status_sizeof); _PA_LOAD_FUNC(snd_pcm_status_get_tstamp); + _PA_LOAD_FUNC(snd_pcm_status_get_htstamp); _PA_LOAD_FUNC(snd_pcm_status_get_state); _PA_LOAD_FUNC(snd_pcm_status_get_trigger_tstamp); + _PA_LOAD_FUNC(snd_pcm_status_get_trigger_htstamp); _PA_LOAD_FUNC(snd_pcm_status_get_delay); _PA_LOAD_FUNC(snd_card_next); @@ -569,7 +575,7 @@ static void PaAlsa_CloseLibrary() { \ PaUtil_SetLastHostErrorInfo( paALSA, __pa_unsure_error_id, alsa_snd_strerror( __pa_unsure_error_id ) ); \ } \ - PaUtil_DebugPrint( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" ); \ + PaUtil_DebugPrint( "Expression '" #expr "' failed in '" __FILE__ "', line: " PA_STRINGIZE( __LINE__ ) "\n" ); \ if( (code) == paUnanticipatedHostError ) \ PA_DEBUG(( "Host error description: %s\n", alsa_snd_strerror( __pa_unsure_error_id ) )); \ result = (code); \ @@ -676,7 +682,7 @@ PaAlsaHostApiRepresentation; typedef struct PaAlsaDeviceInfo { PaDeviceInfo baseDeviceInfo; - const char *alsaName; + char *alsaName; int isPlug; int minInputChannels; int minOutputChannels; @@ -743,7 +749,7 @@ PaError PaAlsa_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex if (!PaAlsa_LoadLibrary()) return paHostApiNotFound; - PA_UNLESS( alsaHostApi = (PaAlsaHostApiRepresentation*) PaUtil_AllocateMemory( + PA_UNLESS( alsaHostApi = (PaAlsaHostApiRepresentation*) PaUtil_AllocateZeroInitializedMemory( sizeof(PaAlsaHostApiRepresentation) ), paInsufficientMemory ); PA_UNLESS( alsaHostApi->allocations = PaUtil_CreateAllocationGroup(), paInsufficientMemory ); alsaHostApi->hostApiIndex = hostApiIndex; @@ -837,12 +843,12 @@ static PaError GropeDevice( snd_pcm_t* pcm, int isPlug, StreamDirection mode, in PaError result = paNoError; snd_pcm_hw_params_t *hwParams; snd_pcm_uframes_t alsaBufferFrames, alsaPeriodFrames; - unsigned int minChans, maxChans; + unsigned int minChans = 0; + unsigned int maxChans = 0; int* minChannels, * maxChannels; double * defaultLowLatency, * defaultHighLatency, * defaultSampleRate = &devInfo->baseDeviceInfo.defaultSampleRate; double defaultSr = *defaultSampleRate; - int dir; assert( pcm ); @@ -896,9 +902,22 @@ static PaError GropeDevice( snd_pcm_t* pcm, int isPlug, StreamDirection mode, in ENSURE_( alsa_snd_pcm_hw_params_get_channels_min( hwParams, &minChans ), paUnanticipatedHostError ); ENSURE_( alsa_snd_pcm_hw_params_get_channels_max( hwParams, &maxChans ), paUnanticipatedHostError ); - assert( maxChans <= INT_MAX ); - assert( maxChans > 0 ); /* Weird linking issue could cause wrong version of ALSA symbols to be called, + const unsigned int kReasonableMaxChannels = 1024; + if( maxChans > kReasonableMaxChannels ) + { + PA_DEBUG(( "%s: maxChans = %u, which is unreasonably high\n", __FUNCTION__, maxChans )); + result = paUnanticipatedHostError; + goto error; + } + else if( maxChans == 0 ) + { + /* Weird linking issue could cause wrong version of ALSA symbols to be called, resulting in zeroed values */ + PA_DEBUG(( "%s: minChans = %u, maxChans = %u, linking problem?\n", + __FUNCTION__, minChans, maxChans )); + result = paUnanticipatedHostError; + goto error; + } /* XXX: Limit to sensible number (ALSA plugins accept a crazy amount of channels)? */ if( isPlug && maxChans > 128 ) @@ -920,7 +939,7 @@ static PaError GropeDevice( snd_pcm_t* pcm, int isPlug, StreamDirection mode, in alsaBufferFrames = 512; alsaPeriodFrames = 128; ENSURE_( alsa_snd_pcm_hw_params_set_buffer_size_near( pcm, hwParams, &alsaBufferFrames ), paUnanticipatedHostError ); - ENSURE_( alsa_snd_pcm_hw_params_set_period_size_near( pcm, hwParams, &alsaPeriodFrames, &dir ), paUnanticipatedHostError ); + ENSURE_( alsa_snd_pcm_hw_params_set_period_size_near( pcm, hwParams, &alsaPeriodFrames, NULL ), paUnanticipatedHostError ); *defaultLowLatency = (double) (alsaBufferFrames - alsaPeriodFrames) / defaultSr; /* Base the high latency case on values four times larger */ @@ -930,7 +949,7 @@ static PaError GropeDevice( snd_pcm_t* pcm, int isPlug, StreamDirection mode, in ENSURE_( alsa_snd_pcm_hw_params_any( pcm, hwParams ), paUnanticipatedHostError ); ENSURE_( SetApproximateSampleRate( pcm, hwParams, defaultSr ), paUnanticipatedHostError ); ENSURE_( alsa_snd_pcm_hw_params_set_buffer_size_near( pcm, hwParams, &alsaBufferFrames ), paUnanticipatedHostError ); - ENSURE_( alsa_snd_pcm_hw_params_set_period_size_near( pcm, hwParams, &alsaPeriodFrames, &dir ), paUnanticipatedHostError ); + ENSURE_( alsa_snd_pcm_hw_params_set_period_size_near( pcm, hwParams, &alsaPeriodFrames, NULL ), paUnanticipatedHostError ); *defaultHighLatency = (double) (alsaBufferFrames - alsaPeriodFrames) / defaultSr; *minChannels = (int)minChans; @@ -982,7 +1001,7 @@ static PaUint32 PaAlsaVersionNum(void) /* Helper struct */ typedef struct { - const char *alsaName; + char *alsaName; char *name; int isPlug; int hasPlayback; @@ -1051,7 +1070,7 @@ static PaError PaAlsa_StrDup( PaAlsaHostApiRepresentation *alsaApi, /* PA_DEBUG(("PaStrDup %s %d\n", src, len)); */ - PA_UNLESS( *dst = (char *)PaUtil_GroupAllocateMemory( alsaApi->allocations, len ), + PA_UNLESS( *dst = (char *)PaUtil_GroupAllocateZeroInitializedMemory( alsaApi->allocations, len ), paInsufficientMemory ); strncpy( *dst, src, len ); @@ -1066,6 +1085,10 @@ static int IgnorePlugin( const char *pluginId ) static const char *ignoredPlugins[] = {"hw", "plughw", "plug", "dsnoop", "tee", "file", "null", "shm", "cards", "rate_convert", NULL}; int i = 0; + + if( getenv( "PA_ALSA_IGNORE_ALL_PLUGINS" ) && atoi( getenv( "PA_ALSA_IGNORE_ALL_PLUGINS") ) ) + return 1; + while( ignoredPlugins[i] ) { if( !strcmp( pluginId, ignoredPlugins[i] ) ) @@ -1079,9 +1102,9 @@ static int IgnorePlugin( const char *pluginId ) } /* Skip past parts at the beginning of a (pcm) info name that are already in the card name, to avoid duplication */ -static const char *SkipCardDetailsInName( const char *infoSkipName, const char *cardRefName ) +static char *SkipCardDetailsInName( char *infoSkipName, char *cardRefName ) { - const char *lastSpacePosn = infoSkipName; + char *lastSpacePosn = infoSkipName; /* Skip matching chars; but only in chunks separated by ' ' (not part words etc), so track lastSpacePosn */ while( *cardRefName ) @@ -1238,7 +1261,7 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ) int res; int blocking = SND_PCM_NONBLOCK; int usePlughw = 0; - const char *hwPrefix = ""; + char *hwPrefix = ""; char alsaCardName[50]; #ifdef PA_ENABLE_DEBUG_OUTPUT PaTime startTime = PaUtil_GetTime(); @@ -1275,7 +1298,7 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ) char *cardName; int devIdx = -1; snd_ctl_t *ctl; - char buf[50]; + char buf[66]; snprintf( alsaCardName, sizeof (alsaCardName), "hw:%d", cardIdx ); @@ -1292,8 +1315,7 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ) while( alsa_snd_ctl_pcm_next_device( ctl, &devIdx ) == 0 && devIdx >= 0 ) { - char *alsaDeviceName, *deviceName; - const char *infoName; + char *alsaDeviceName, *deviceName, *infoName; size_t len; int hasPlayback = 0, hasCapture = 0; @@ -1320,14 +1342,16 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ) continue; } - infoName = SkipCardDetailsInName( alsa_snd_pcm_info_get_name( pcmInfo ), cardName ); + infoName = SkipCardDetailsInName( (char *)alsa_snd_pcm_info_get_name( pcmInfo ), cardName ); /* The length of the string written by snprintf plus terminating 0 */ len = snprintf( NULL, 0, "%s: %s (%s)", cardName, infoName, buf ) + 1; - PA_UNLESS( deviceName = (char *)PaUtil_GroupAllocateMemory( alsaApi->allocations, len ), + PA_UNLESS( deviceName = (char *)PaUtil_GroupAllocateZeroInitializedMemory( alsaApi->allocations, len ), paInsufficientMemory ); snprintf( deviceName, len, "%s: %s (%s)", cardName, infoName, buf ); + PA_DEBUG(( "%s: Found device [%d]: %s\n", __FUNCTION__, numDeviceNames, deviceName )); + ++numDeviceNames; if( !hwDevInfos || numDeviceNames > maxDeviceNames ) { @@ -1387,10 +1411,10 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ) } PA_DEBUG(( "%s: Found plugin [%s] of type [%s]\n", __FUNCTION__, idStr, tpStr )); - PA_UNLESS( alsaDeviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations, + PA_UNLESS( alsaDeviceName = (char*)PaUtil_GroupAllocateZeroInitializedMemory( alsaApi->allocations, strlen(idStr) + 6 ), paInsufficientMemory ); strcpy( alsaDeviceName, idStr ); - PA_UNLESS( deviceName = (char*)PaUtil_GroupAllocateMemory( alsaApi->allocations, + PA_UNLESS( deviceName = (char*)PaUtil_GroupAllocateZeroInitializedMemory( alsaApi->allocations, strlen(idStr) + 1 ), paInsufficientMemory ); strcpy( deviceName, idStr ); @@ -1424,11 +1448,11 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ) PA_DEBUG(( "%s: Iterating over ALSA plugins failed: %s\n", __FUNCTION__, alsa_snd_strerror( res ) )); /* allocate deviceInfo memory based on the number of devices */ - PA_UNLESS( baseApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( + PA_UNLESS( baseApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateZeroInitializedMemory( alsaApi->allocations, sizeof(PaDeviceInfo*) * (numDeviceNames) ), paInsufficientMemory ); /* allocate all device info structs in a contiguous block */ - PA_UNLESS( deviceInfoArray = (PaAlsaDeviceInfo*)PaUtil_GroupAllocateMemory( + PA_UNLESS( deviceInfoArray = (PaAlsaDeviceInfo*)PaUtil_GroupAllocateZeroInitializedMemory( alsaApi->allocations, sizeof(PaAlsaDeviceInfo) * numDeviceNames ), paInsufficientMemory ); /* Loop over list of cards, filling in info. If a device is deemed unavailable (can't get name), @@ -1451,7 +1475,7 @@ static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi ) PA_ENSURE( FillInDevInfo( alsaApi, hwInfo, blocking, devInfo, &devIdx ) ); } - assert( devIdx < numDeviceNames ); + assert( devIdx <= numDeviceNames ); /* Now inspect 'dmix' and 'default' plugins */ for( i = 0; i < numDeviceNames; ++i ) { @@ -1917,7 +1941,7 @@ static PaError PaAlsaStreamComponent_Initialize( PaAlsaStreamComponent *self, Pa if( !callbackMode && !self->userInterleaved ) { /* Pre-allocate non-interleaved user provided buffers */ - PA_UNLESS( self->userBuffers = PaUtil_AllocateMemory( sizeof (void *) * self->numUserChannels ), + PA_UNLESS( self->userBuffers = PaUtil_AllocateZeroInitializedMemory( sizeof (void *) * self->numUserChannels ), paInsufficientMemory ); } @@ -1956,7 +1980,7 @@ static PaError PaAlsaStreamComponent_InitialConfigure( PaAlsaStreamComponent *se { /* Configuration consists of setting all of ALSA's parameters. * These parameters come in two flavors: hardware parameters - * and software paramters. Hardware parameters will affect + * and software parameters. Hardware parameters will affect * the way the device is initialized, software parameters * affect the way ALSA interacts with me, the user-level client. */ @@ -1970,7 +1994,7 @@ static PaError PaAlsaStreamComponent_InitialConfigure( PaAlsaStreamComponent *se /* self->framesPerPeriod = framesPerHostBuffer; */ - /* ... fill up the configuration space with all possibile + /* ... fill up the configuration space with all possible * combinations of parameters this device will accept */ ENSURE_( alsa_snd_pcm_hw_params_any( pcm, hwParams ), paUnanticipatedHostError ); @@ -2046,7 +2070,7 @@ static PaError PaAlsaStreamComponent_InitialConfigure( PaAlsaStreamComponent *se } else { - PA_ENSURE( paUnanticipatedHostError ); + PA_ENSURE( paUnanticipatedHostError ); } ENSURE_( alsa_snd_pcm_hw_params_set_channels( pcm, hwParams, self->numHostChannels ), paInvalidChannelCount ); @@ -2155,7 +2179,7 @@ static PaError PaAlsaStream_Initialize( PaAlsaStream *self, PaAlsaHostApiReprese self->framesPerUserBuffer = framesPerUserBuffer; self->neverDropInput = streamFlags & paNeverDropInput; - /* XXX: Ignore paPrimeOutputBuffersUsingStreamCallback untill buffer priming is fully supported in pa_process.c */ + /* XXX: Ignore paPrimeOutputBuffersUsingStreamCallback until buffer priming is fully supported in pa_process.c */ /* if( outParams & streamFlags & paPrimeOutputBuffersUsingStreamCallback ) self->primeBuffers = 1; @@ -2173,7 +2197,7 @@ static PaError PaAlsaStream_Initialize( PaAlsaStream *self, PaAlsaHostApiReprese assert( self->capture.nfds || self->playback.nfds ); - PA_UNLESS( self->pfds = (struct pollfd*)PaUtil_AllocateMemory( ( self->capture.nfds + + PA_UNLESS( self->pfds = (struct pollfd*)PaUtil_AllocateZeroInitializedMemory( ( self->capture.nfds + self->playback.nfds ) * sizeof( struct pollfd ) ), paInsufficientMemory ); PaUtil_InitializeCpuLoadMeasurer( &self->cpuLoadMeasurer, sampleRate ); @@ -2325,6 +2349,7 @@ static PaError PaAlsaStreamComponent_DetermineFramesPerBuffer( PaAlsaStreamCompo /* It may be that the device only supports 2 periods for instance */ dir = 0; ENSURE_( alsa_snd_pcm_hw_params_get_periods_min( hwParams, &minPeriods, &dir ), paUnanticipatedHostError ); + dir = 0; ENSURE_( alsa_snd_pcm_hw_params_get_periods_max( hwParams, &maxPeriods, &dir ), paUnanticipatedHostError ); assert( maxPeriods > 1 ); @@ -2382,7 +2407,7 @@ static PaError PaAlsaStreamComponent_DetermineFramesPerBuffer( PaAlsaStreamCompo { framesPerHostBuffer *= 2; } - /* One extra period is preferrable to one less (should be more robust) */ + /* One extra period is preferable to one less (should be more robust) */ if( bufferSize / framesPerHostBuffer < numPeriods ) { framesPerHostBuffer /= 2; @@ -2683,7 +2708,7 @@ static PaError PaAlsaStream_DetermineFramesPerBuffer( PaAlsaStream* self, double PA_UNLESS( framesPerHostBuffer != 0, paInternalError ); self->maxFramesPerHostBuffer = framesPerHostBuffer; - if( !self->playback.canMmap || !accurate ) + if( (self->playback.pcm && !self->playback.canMmap) || !accurate ) { /* Don't know the exact size per host buffer */ *hostBufferSizeMode = paUtilBoundedHostBufferSize; @@ -2831,7 +2856,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, framesPerBuffer = atoi( getenv("PA_ALSA_PERIODSIZE") ); } - PA_UNLESS( stream = (PaAlsaStream*)PaUtil_AllocateMemory( sizeof(PaAlsaStream) ), paInsufficientMemory ); + PA_UNLESS( stream = (PaAlsaStream*)PaUtil_AllocateZeroInitializedMemory( sizeof(PaAlsaStream) ), paInsufficientMemory ); PA_ENSURE( PaAlsaStream_Initialize( stream, alsaHostApi, inputParameters, outputParameters, sampleRate, framesPerBuffer, callback, streamFlags, userData ) ); @@ -3149,6 +3174,28 @@ static PaError IsStreamActive( PaStream *s ) return stream->isActive; } +/** Extract audio/trigger htstamp from status and convert into PaTime (seconds). + * + * trigger is boolean: trigger stampstamp vs audio timestamp. If delay is non-NULL, return delay in + * frames. */ +static PaTime StatusToTime( const snd_pcm_status_t *status, int trigger, snd_pcm_uframes_t* delay ) +{ + snd_htimestamp_t timestamp; + if ( trigger ) + { + alsa_snd_pcm_status_get_trigger_htstamp( status, ×tamp ); + } + else + { + alsa_snd_pcm_status_get_htstamp( status, ×tamp ); + } + if ( delay ) + { + *delay = alsa_snd_pcm_status_get_delay( status ); + } + return timestamp.tv_sec + ( (PaTime)timestamp.tv_nsec * 1e-9 ); +} + static PaTime GetStreamTime( PaStream *s ) { PaAlsaStream *stream = (PaAlsaStream*)s; @@ -3172,8 +3219,7 @@ static PaTime GetStreamTime( PaStream *s ) alsa_snd_pcm_status( stream->playback.pcm, status ); } - alsa_snd_pcm_status_get_tstamp( status, ×tamp ); - return timestamp.tv_sec + (PaTime)timestamp.tv_usec / 1e6; + return StatusToTime( status, 0, NULL ); } static double GetStreamCpuLoad( PaStream* s ) @@ -3197,7 +3243,7 @@ static int SetApproximateSampleRate( snd_pcm_t *pcm, snd_pcm_hw_params_t *hwPara ENSURE_( alsa_snd_pcm_hw_params_set_rate_near( pcm, hwParams, &setRate, NULL ), paUnanticipatedHostError ); /* The value actually set will be put in 'setRate' (may be way off); check the deviation as a proportion * of the requested-rate with reference to the max-deviate-ratio (larger values allow less deviation) */ - deviation = abs( setRate - reqRate ); + deviation = abs( (int)setRate - (int)reqRate ); if( deviation > 0 && deviation * RATE_MAX_DEVIATE_RATIO > reqRate ) result = paInvalidSampleRate; @@ -3210,6 +3256,7 @@ error: unsigned int _min = 0, _max = 0; int _dir = 0; ENSURE_( alsa_snd_pcm_hw_params_get_rate_min( hwParams, &_min, &_dir ), paUnanticipatedHostError ); + _dir = 0; ENSURE_( alsa_snd_pcm_hw_params_get_rate_max( hwParams, &_max, &_dir ), paUnanticipatedHostError ); PA_DEBUG(( "%s: SR min = %u, max = %u, req = %u\n", __FUNCTION__, _min, _max, reqRate )); } @@ -3268,7 +3315,7 @@ static PaError PaAlsaStream_HandleXrun( PaAlsaStream *self ) if( alsa_snd_pcm_status_get_state( st ) == SND_PCM_STATE_XRUN ) { alsa_snd_pcm_status_get_trigger_tstamp( st, &t ); - self->underrun = now * 1000 - ( (PaTime)t.tv_sec * 1000 + (PaTime)t.tv_usec / 1000 ); + self->underrun = ( now - StatusToTime( st, 1, NULL ) ) * 1000; if( !self->playback.canMmap ) { @@ -3287,8 +3334,7 @@ static PaError PaAlsaStream_HandleXrun( PaAlsaStream *self ) alsa_snd_pcm_status( self->capture.pcm, st ); if( alsa_snd_pcm_status_get_state( st ) == SND_PCM_STATE_XRUN ) { - alsa_snd_pcm_status_get_trigger_tstamp( st, &t ); - self->overrun = now * 1000 - ((PaTime) t.tv_sec * 1000 + (PaTime) t.tv_usec / 1000); + self->overrun = ( now - StatusToTime( st, 1, NULL ) ) * 1000; if (!self->capture.canMmap) { @@ -3400,37 +3446,29 @@ static void OnExit( void *data ) static void CalculateTimeInfo( PaAlsaStream *stream, PaStreamCallbackTimeInfo *timeInfo ) { - snd_pcm_status_t *capture_status, *playback_status; - snd_timestamp_t capture_timestamp, playback_timestamp; + snd_pcm_status_t *status; PaTime capture_time = 0., playback_time = 0.; - alsa_snd_pcm_status_alloca( &capture_status ); - alsa_snd_pcm_status_alloca( &playback_status ); + alsa_snd_pcm_status_alloca( &status ); if( stream->capture.pcm ) { snd_pcm_sframes_t capture_delay; - alsa_snd_pcm_status( stream->capture.pcm, capture_status ); - alsa_snd_pcm_status_get_tstamp( capture_status, &capture_timestamp ); + alsa_snd_pcm_status( stream->capture.pcm, status ); + capture_time = StatusToTime( status, 0, &capture_delay ); - capture_time = capture_timestamp.tv_sec + - ( (PaTime)capture_timestamp.tv_usec / 1000000.0 ); timeInfo->currentTime = capture_time; - - capture_delay = alsa_snd_pcm_status_get_delay( capture_status ); - timeInfo->inputBufferAdcTime = timeInfo->currentTime - + timeInfo->inputBufferAdcTime = capture_time - (PaTime)capture_delay / stream->streamRepresentation.streamInfo.sampleRate; } if( stream->playback.pcm ) { snd_pcm_sframes_t playback_delay; + PaTime playback_time; - alsa_snd_pcm_status( stream->playback.pcm, playback_status ); - alsa_snd_pcm_status_get_tstamp( playback_status, &playback_timestamp ); - - playback_time = playback_timestamp.tv_sec + - ((PaTime)playback_timestamp.tv_usec / 1000000.0); + alsa_snd_pcm_status( stream->playback.pcm, status ); + playback_time = StatusToTime( status, 0, &playback_delay ); if( stream->capture.pcm ) /* Full duplex */ { @@ -3442,7 +3480,6 @@ static void CalculateTimeInfo( PaAlsaStream *stream, PaStreamCallbackTimeInfo *t else timeInfo->currentTime = playback_time; - playback_delay = alsa_snd_pcm_status_get_delay( playback_status ); timeInfo->outputBufferDacTime = timeInfo->currentTime + (PaTime)playback_delay / stream->streamRepresentation.streamInfo.sampleRate; } @@ -3489,10 +3526,18 @@ static PaError PaAlsaStreamComponent_EndProcessing( PaAlsaStreamComponent *self, if( self->canMmap ) res = alsa_snd_pcm_mmap_commit( self->pcm, self->offset, numFrames ); - if( res == -EPIPE || res == -ESTRPIPE ) + if( res == -EPIPE ) + { + *xrun = 1; + } + // ESTRPIPE is provided by the Linux kernel headers, and is unavailable + // on the BSDs, which can still use alsalib. +#if defined(ESTRPIPE) && ESTRPIPE != EPIPE + else if( res == -ESTRPIPE ) { *xrun = 1; } +#endif else { ENSURE_( res, paUnanticipatedHostError ); @@ -3631,14 +3676,15 @@ error: */ static PaError PaAlsaStreamComponent_BeginPolling( PaAlsaStreamComponent* self, struct pollfd* pfds ) { - PaError result = paNoError; - int ret = alsa_snd_pcm_poll_descriptors( self->pcm, pfds, self->nfds ); - (void)ret; /* Prevent unused variable warning if asserts are turned off */ - assert( ret == self->nfds ); - + int nfds = alsa_snd_pcm_poll_descriptors( self->pcm, pfds, self->nfds ); + /* If alsa returns anything else, like -EPIPE return */ + if( nfds != self->nfds ) + { + return paUnanticipatedHostError; + } self->ready = 0; - return result; + return paNoError; } /** Examine results from poll(). @@ -3795,14 +3841,24 @@ static PaError PaAlsaStream_WaitForFrames( PaAlsaStream *self, unsigned long *fr if( pollCapture ) { capturePfds = self->pfds; - PA_ENSURE( PaAlsaStreamComponent_BeginPolling( &self->capture, capturePfds ) ); + PaError res = PaAlsaStreamComponent_BeginPolling( &self->capture, capturePfds ); + if( res != paNoError) + { + xrun = 1; + goto end; + } totalFds += self->capture.nfds; } if( pollPlayback ) { /* self->pfds is in effect an array of fds; if necessary, index past the capture fds */ playbackPfds = self->pfds + (pollCapture ? self->capture.nfds : 0); - PA_ENSURE( PaAlsaStreamComponent_BeginPolling( &self->playback, playbackPfds ) ); + PaError res = PaAlsaStreamComponent_BeginPolling( &self->playback, playbackPfds ); + if( res != paNoError) + { + xrun = 1; + goto end; + } totalFds += self->playback.nfds; } @@ -4048,11 +4104,20 @@ static PaError PaAlsaStreamComponent_RegisterChannels( PaAlsaStreamComponent* se } res = alsa_snd_pcm_readn( self->pcm, bufs, *numFrames ); } - if( res == -EPIPE || res == -ESTRPIPE ) + if( res == -EPIPE ) + { + *xrun = 1; + *numFrames = 0; + } + // ESTRPIPE is provided by the Linux kernel headers, and is unavailable + // on the BSDs, which can still use alsalib. +#if defined(ESTRPIPE) && ESTRPIPE != EPIPE + else if( res == -ESTRPIPE ) { *xrun = 1; *numFrames = 0; } +#endif } end: @@ -4178,7 +4243,7 @@ error: * directly is obtained from ALSA, we then request as much directly accessible memory as possible within this amount * from ALSA. The buffer memory is registered with the PA buffer processor and processing is carried out with * PaUtil_EndBufferProcessing. Finally, the number of processed frames is reported to ALSA. The processing can - * happen in several iterations untill we have consumed the known number of available frames (or an xrun is detected). + * happen in several iterations until we have consumed the known number of available frames (or an xrun is detected). */ static void *CallbackThreadFunc( void *userData ) { @@ -4264,7 +4329,7 @@ static void *CallbackThreadFunc( void *userData ) /* There is still buffered output that needs to be processed */ } - /* Wait for data to become available, this comes down to polling the ALSA file descriptors untill we have + /* Wait for data to become available, this comes down to polling the ALSA file descriptors until we have * a number of available frames. */ PA_ENSURE( PaAlsaStream_WaitForFrames( stream, &framesAvail, &xrun ) ); @@ -4601,6 +4666,7 @@ PaError PaAlsa_GetStreamInputCard( PaStream* s, int* card ) PaError result = paNoError; snd_pcm_info_t* pcmInfo; + stream = NULL; PA_ENSURE( GetAlsaStreamPointer( s, &stream ) ); /* XXX: More descriptive error? */ @@ -4620,6 +4686,7 @@ PaError PaAlsa_GetStreamOutputCard( PaStream* s, int* card ) PaError result = paNoError; snd_pcm_info_t* pcmInfo; + stream = NULL; PA_ENSURE( GetAlsaStreamPointer( s, &stream ) ); /* XXX: More descriptive error? */ diff --git a/3rdparty/portaudio/src/hostapi/asihpi/pa_linux_asihpi.c b/3rdparty/portaudio/src/hostapi/asihpi/pa_linux_asihpi.c index f5a52902848..db8efcc21a9 100644 --- a/3rdparty/portaudio/src/hostapi/asihpi/pa_linux_asihpi.c +++ b/3rdparty/portaudio/src/hostapi/asihpi/pa_linux_asihpi.c @@ -175,7 +175,7 @@ PaError paError = (expr); \ if( UNLIKELY( paError < paNoError ) ) \ { \ - PA_DEBUG(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \ + PA_DEBUG(( "Expression '" #expr "' failed in '" __FILE__ "', line: " PA_STRINGIZE( __LINE__ ) "\n" )); \ result = paError; \ goto error; \ } \ @@ -186,7 +186,7 @@ do { \ if( UNLIKELY( (expr) == 0 ) ) \ { \ - PA_DEBUG(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \ + PA_DEBUG(( "Expression '" #expr "' failed in '" __FILE__ "', line: " PA_STRINGIZE( __LINE__ ) "\n" )); \ result = (paError); \ goto error; \ } \ @@ -199,27 +199,27 @@ /* If HPI error occurred */ \ if( UNLIKELY( hpiError ) ) \ { \ - char szError[256]; \ - HPI_GetErrorText( hpiError, szError ); \ - PA_DEBUG(( "HPI error %d occurred: %s\n", hpiError, szError )); \ - /* This message will always be displayed, even if debug info is disabled */ \ - PA_DEBUG(( "Expression '" #expr "' failed in '" __FILE__ "', line: " STRINGIZE( __LINE__ ) "\n" )); \ + char szError[256]; \ + HPI_GetErrorText( hpiError, szError ); \ + PA_DEBUG(( "HPI error %d occurred: %s\n", hpiError, szError )); \ + /* This message will always be displayed, even if debug info is disabled */ \ + PA_DEBUG(( "Expression '" #expr "' failed in '" __FILE__ "', line: " PA_STRINGIZE( __LINE__ ) "\n" )); \ if( (paError) == paUnanticipatedHostError ) \ - { \ - PA_DEBUG(( "Host error description: %s\n", szError )); \ - /* PaUtil_SetLastHostErrorInfo should only be used in the main thread */ \ - if( pthread_equal( pthread_self(), paUnixMainThread ) ) \ + { \ + PA_DEBUG(( "Host error description: %s\n", szError )); \ + /* PaUtil_SetLastHostErrorInfo should only be used in the main thread */ \ + if( pthread_equal( pthread_self(), paUnixMainThread ) ) \ { \ - PaUtil_SetLastHostErrorInfo( paInDevelopment, hpiError, szError ); \ + PaUtil_SetLastHostErrorInfo( paInDevelopment, hpiError, szError ); \ } \ - } \ - /* If paNoError is specified, continue as usual */ \ + } \ + /* If paNoError is specified, continue as usual */ \ /* (useful if you only want to print out the debug messages above) */ \ - if( (paError) < 0 ) \ - { \ - result = (paError); \ - goto error; \ - } \ + if( (paError) < 0 ) \ + { \ + result = (paError); \ + goto error; \ + } \ } \ } while( 0 ); @@ -231,9 +231,9 @@ PA_DEBUG(( "HPI error %d occurred: %s\n", hpiError, szError )); \ /* PaUtil_SetLastHostErrorInfo should only be used in the main thread */ \ if( pthread_equal( pthread_self(), paUnixMainThread ) ) \ - { \ - PaUtil_SetLastHostErrorInfo( paInDevelopment, (hpiErrorCode), szError ); \ - } \ + { \ + PaUtil_SetLastHostErrorInfo( paInDevelopment, (hpiErrorCode), szError ); \ + } \ } while( 0 ); /* Defaults */ @@ -556,7 +556,7 @@ static PaError PaAsiHpi_BuildDeviceList( PaAsiHpiHostApiRepresentation *hpiHostA continue; } hpiError = HPI_AdapterGetInfo( NULL, idx, &outStreams, &inStreams, - &version, &serial, &type ); + &version, &serial, &type ); /* Skip to next device on failure */ if( hpiError ) { @@ -579,11 +579,11 @@ static PaError PaAsiHpi_BuildDeviceList( PaAsiHpiHostApiRepresentation *hpiHostA if( deviceCount > 0 ) { /* Memory allocation */ - PA_UNLESS_( hostApi->deviceInfos = (PaDeviceInfo**) PaUtil_GroupAllocateMemory( + PA_UNLESS_( hostApi->deviceInfos = (PaDeviceInfo**) PaUtil_GroupAllocateZeroInitializedMemory( hpiHostApi->allocations, sizeof(PaDeviceInfo*) * deviceCount ), paInsufficientMemory ); /* Allocate all device info structs in a contiguous block */ - PA_UNLESS_( hpiDeviceList = (PaAsiHpiDeviceInfo*) PaUtil_GroupAllocateMemory( + PA_UNLESS_( hpiDeviceList = (PaAsiHpiDeviceInfo*) PaUtil_GroupAllocateZeroInitializedMemory( hpiHostApi->allocations, sizeof(PaAsiHpiDeviceInfo) * deviceCount ), paInsufficientMemory ); @@ -640,7 +640,7 @@ static PaError PaAsiHpi_BuildDeviceList( PaAsiHpiHostApiRepresentation *hpiHostA /* Make sure name string is owned by API info structure */ sprintf( srcName, "Adapter %d (%4X) - Input Stream %d", i+1, type, j+1 ); - PA_UNLESS_( deviceName = (char *) PaUtil_GroupAllocateMemory( + PA_UNLESS_( deviceName = (char *) PaUtil_GroupAllocateZeroInitializedMemory( hpiHostApi->allocations, strlen(srcName) + 1 ), paInsufficientMemory ); strcpy( deviceName, srcName ); baseDeviceInfo->name = deviceName; @@ -682,7 +682,7 @@ static PaError PaAsiHpi_BuildDeviceList( PaAsiHpiHostApiRepresentation *hpiHostA /* Make sure name string is owned by API info structure */ sprintf( srcName, "Adapter %d (%4X) - Output Stream %d", i+1, type, j+1 ); - PA_UNLESS_( deviceName = (char *) PaUtil_GroupAllocateMemory( + PA_UNLESS_( deviceName = (char *) PaUtil_GroupAllocateZeroInitializedMemory( hpiHostApi->allocations, strlen(srcName) + 1 ), paInsufficientMemory ); strcpy( deviceName, srcName ); baseDeviceInfo->name = deviceName; @@ -738,7 +738,7 @@ PaError PaAsiHpi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd * interface and paNoError */ PA_DEBUG(( "Could not open HPI interface\n" )); - *hostApi = NULL; + *hostApi = NULL; return paNoError; } else @@ -750,7 +750,7 @@ PaError PaAsiHpi_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd } /* Allocate host API structure */ - PA_UNLESS_( hpiHostApi = (PaAsiHpiHostApiRepresentation*) PaUtil_AllocateMemory( + PA_UNLESS_( hpiHostApi = (PaAsiHpiHostApiRepresentation*) PaUtil_AllocateZeroInitializedMemory( sizeof(PaAsiHpiHostApiRepresentation) ), paInsufficientMemory ); PA_UNLESS_( hpiHostApi->allocations = PaUtil_CreateAllocationGroup(), paInsufficientMemory ); @@ -1584,7 +1584,7 @@ static PaError PaAsiHpi_SetupBuffers( PaAsiHpiStreamComponent *streamComp, uint3 /* If BBM not supported, foreground transfers will be used, but not a show-stopper */ /* Anything else is an error */ else if (( hpiError != HPI_ERROR_INVALID_OPERATION ) && - ( hpiError != HPI_ERROR_INVALID_FUNC )) + ( hpiError != HPI_ERROR_INVALID_FUNC )) { PA_ASIHPI_REPORT_ERROR_( hpiError ); result = paUnanticipatedHostError; @@ -1622,7 +1622,7 @@ static PaError PaAsiHpi_SetupBuffers( PaAsiHpiStreamComponent *streamComp, uint3 /* Temp buffer size should be multiple of PA host buffer size (or 1x, if using fixed blocks) */ streamComp->tempBufferSize = paHostBufferSize; /* Allocate temp buffer */ - PA_UNLESS_( streamComp->tempBuffer = (uint8_t *)PaUtil_AllocateMemory( streamComp->tempBufferSize ), + PA_UNLESS_( streamComp->tempBuffer = (uint8_t *)PaUtil_AllocateZeroInitializedMemory( streamComp->tempBufferSize ), paInsufficientMemory ); error: return result; @@ -1682,9 +1682,8 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, return paInvalidFlag; /* unexpected platform-specific flag */ /* Create blank stream structure */ - PA_UNLESS_( stream = (PaAsiHpiStream *)PaUtil_AllocateMemory( sizeof(PaAsiHpiStream) ), + PA_UNLESS_( stream = (PaAsiHpiStream *)PaUtil_AllocateZeroInitializedMemory( sizeof(PaAsiHpiStream) ), paInsufficientMemory ); - memset( stream, 0, sizeof(PaAsiHpiStream) ); /* If the number of frames per buffer is unspecified, we have to come up with one. */ if( framesPerHostBuffer == paFramesPerBufferUnspecified ) @@ -1719,9 +1718,8 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, if( inputParameters ) { /* Create blank stream component structure */ - PA_UNLESS_( stream->input = (PaAsiHpiStreamComponent *)PaUtil_AllocateMemory( sizeof(PaAsiHpiStreamComponent) ), + PA_UNLESS_( stream->input = (PaAsiHpiStreamComponent *)PaUtil_AllocateZeroInitializedMemory( sizeof(PaAsiHpiStreamComponent) ), paInsufficientMemory ); - memset( stream->input, 0, sizeof(PaAsiHpiStreamComponent) ); /* Create/validate format */ PA_ENSURE_( PaAsiHpi_CreateFormat( hostApi, inputParameters, sampleRate, &stream->input->hpiDevice, &stream->input->hpiFormat ) ); @@ -1740,9 +1738,8 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, if( outputParameters ) { /* Create blank stream component structure */ - PA_UNLESS_( stream->output = (PaAsiHpiStreamComponent *)PaUtil_AllocateMemory( sizeof(PaAsiHpiStreamComponent) ), + PA_UNLESS_( stream->output = (PaAsiHpiStreamComponent *)PaUtil_AllocateZeroInitializedMemory( sizeof(PaAsiHpiStreamComponent) ), paInsufficientMemory ); - memset( stream->output, 0, sizeof(PaAsiHpiStreamComponent) ); /* Create/validate format */ PA_ENSURE_( PaAsiHpi_CreateFormat( hostApi, outputParameters, sampleRate, &stream->output->hpiDevice, &stream->output->hpiFormat ) ); @@ -1790,7 +1787,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, streamCallback, userData ); /* Pre-allocate non-interleaved user buffer pointers for blocking interface */ PA_UNLESS_( stream->blockingUserBufferCopy = - PaUtil_AllocateMemory( sizeof(void *) * PA_MAX( inputChannelCount, outputChannelCount ) ), + PaUtil_AllocateZeroInitializedMemory( sizeof(void *) * PA_MAX( inputChannelCount, outputChannelCount ) ), paInsufficientMemory ); stream->callbackMode = 0; } diff --git a/3rdparty/portaudio/src/hostapi/asio/ASIO-README.txt b/3rdparty/portaudio/src/hostapi/asio/ASIO-README.txt index bc86caa5be3..9c4f817a0d3 100644 --- a/3rdparty/portaudio/src/hostapi/asio/ASIO-README.txt +++ b/3rdparty/portaudio/src/hostapi/asio/ASIO-README.txt @@ -13,7 +13,7 @@ Building PortAudio with ASIO support ------------------------------------ To build PortAudio with ASIO support you need to compile and link with -pa_asio.c, and files from the ASIO SDK (see below), along with the common +pa_asio.cpp, and files from the ASIO SDK (see below), along with the common PortAudio files from src/common/ and platform specific files from src/os/win/ (for Win32). @@ -32,7 +32,7 @@ path to the ASIO SDK. For Microsoft Visual C++ there is an build tutorial here: -http://www.portaudio.com/trac/wiki/TutorialDir/Compile/WindowsASIOMSVC +http://files.portaudio.com/docs/v19-doxydocs/compile_windows_asio_msvc.html @@ -60,9 +60,9 @@ Building the ASIO SDK on Windows To build the ASIO SDK on Windows you need to compile and link with the following files from the ASIO SDK: -asio_sdk\common\asio.cpp -asio_sdk\host\asiodrivers.cpp -asio_sdk\host\pc\asiolist.cpp +$ASIOSDK\common\asio.cpp +$ASIOSDK\host\asiodrivers.cpp +$ASIOSDK\host\pc\asiolist.cpp You may also need to adjust your include paths to support inclusion of header files from the above directories. @@ -72,6 +72,28 @@ CoInitialize, CoUninitialize, CoCreateInstance, CLSIDFromString For compilation with MinGW you will need to link with -lole32, for Borland compilers link with Import32.lib. +See the next section for information about patching a bug in the SDK. + + +Windows ASIO SDK 2.3 Bug Patch +------------------------------ + +There is a regression in some versions of the ASIO SDK (e.g. version 2.3) +which may trigger a crash in the `deleteDrvStruct()` function in +file `$ASIOSDK\host\pc\asiolist.cpp`. + +To fix this issue replace the line: + delete lpdrv; +with: + delete [] lpdrv; + +Explanation: lpdrv is allocated as an array on the line: + lpdrv = new ASIODRVSTRUCT[1]; +Hence it must also be deleted as an array as per standard C++ rules. + +We are tracking this issue here: +https://github.com/PortAudio/portaudio/issues/331 + Non-Microsoft (MSVC) Compilers on Windows including Borland and GCC @@ -112,6 +134,7 @@ host/mac/codefragements.cpp You may also need to adjust your include paths to support inclusion of header files from the above directories. +See the next section for information about patching a bug in the SDK. (Pre-OS X) Macintosh ASIO SDK Bug Patch diff --git a/3rdparty/portaudio/src/hostapi/asio/pa_asio.cpp b/3rdparty/portaudio/src/hostapi/asio/pa_asio.cpp index f230d8788d4..63ab6a7b828 100644 --- a/3rdparty/portaudio/src/hostapi/asio/pa_asio.cpp +++ b/3rdparty/portaudio/src/hostapi/asio/pa_asio.cpp @@ -29,13 +29,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * 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 + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -46,7 +46,7 @@ 08-20-01 More conversion, PA_StreamTime, Pa_GetHostError : Stephane Letz 08-21-01 PaUInt8 bug correction, implementation of ASIOSTFloat32LSB and ASIOSTFloat32MSB native formats : Stephane Letz 08-24-01 MAX_INT32_FP hack, another Uint8 fix : Stephane and Phil - 08-27-01 Implementation of hostBufferSize < userBufferSize case, better management of the ouput buffer when + 08-27-01 Implementation of hostBufferSize < userBufferSize case, better management of the output buffer when the stream is stopped : Stephane Letz 08-28-01 Check the stream pointer for null in bufferSwitchTimeInfo, correct bug in bufferSwitchTimeInfo when the stream is stopped : Stephane Letz @@ -55,11 +55,11 @@ 10-26-01 Management of hostBufferSize and userBufferSize of any size : Stephane Letz 10-27-01 Improve calculus of hostBufferSize to be multiple or divisor of userBufferSize if possible : Stephane and Phil 10-29-01 Change MAX_INT32_FP to (2147483520.0f) to prevent roundup to 0x80000000 : Phil Burk - 10-31-01 Clear the ouput buffer and user buffers in PaHost_StartOutput, correct bug in GetFirstMultiple : Stephane Letz + 10-31-01 Clear the output buffer and user buffers in PaHost_StartOutput, correct bug in GetFirstMultiple : Stephane Letz 11-06-01 Rename functions : Stephane Letz 11-08-01 New Pa_ASIO_Adaptor_Init function to init Callback adpatation variables, cleanup of Pa_ASIO_Callback_Input: Stephane Letz 11-29-01 Break apart device loading to debug random failure in Pa_ASIO_QueryDeviceInfo ; Phil Burk - 01-03-02 Desallocate all resources in PaHost_Term for cases where Pa_CloseStream is not called properly : Stephane Letz + 01-03-02 Deallocate all resources in PaHost_Term for cases where Pa_CloseStream is not called properly : Stephane Letz 02-01-02 Cleanup, test of multiple-stream opening : Stephane Letz 19-02-02 New Pa_ASIO_loadDriver that calls CoInitialize on each thread on Windows : Stephane Letz 09-04-02 Correct error code management in PaHost_Term, removes various compiler warning : Stephane Letz @@ -69,7 +69,7 @@ 12-06-02 Rehashed into new multi-api infrastructure, added support for all ASIO sample formats : Ross Bencina 18-06-02 Added pa_asio.h, PaAsio_GetAvailableLatencyValues() : Ross B. 21-06-02 Added SelectHostBufferSize() which selects host buffer size based on user latency parameters : Ross Bencina - ** NOTE maintanance history is now stored in CVS ** + ** NOTE maintenance history is now stored in CVS ** */ /** @file @@ -102,8 +102,9 @@ #include "pa_ringbuffer.h" #include "pa_win_coinitialize.h" +#include "pa_win_util.h" -/* This version of pa_asio.cpp is currently only targetted at Win32, +/* This version of pa_asio.cpp is currently only targeted at Win32, It would require a few tweaks to work with pre-OS X Macintosh. To make configuration easier, we define WIN32 here to make sure that the ASIO SDK knows this is Win32. @@ -142,8 +143,8 @@ /* external reference to ASIO SDK's asioDrivers. - This is a bit messy because we want to explicitly manage - allocation/deallocation of this structure, but some layers of the SDK + This is a bit messy because we want to explicitly manage + allocation/deallocation of this structure, but some layers of the SDK which we currently use (eg the implementation in asio.cpp) still use this global version. @@ -214,18 +215,7 @@ static ASIOCallbacks asioCallbacks_ = static void PaAsio_SetLastSystemError( DWORD errorCode ) { - LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - errorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); - PaUtil_SetLastHostErrorInfo( paASIO, errorCode, (const char*)lpMsgBuf ); - LocalFree( lpMsgBuf ); + PaWinUtil_SetLastSystemErrorInfo( paASIO, errorCode ); } #define PA_ASIO_SET_LAST_SYSTEM_ERROR( errorCode ) \ @@ -295,7 +285,7 @@ typedef struct AsioDrivers *asioDrivers; void *systemSpecific; - + /* the ASIO C API only allows one ASIO driver to be open at a time, so we keep track of whether we have the driver open here, and use this information to return errors from OpenStream if the @@ -322,12 +312,12 @@ static char **GetAsioDriverNames( PaAsioHostApiRepresentation *asioHostApi, PaUt char **result = 0; int i; - result =(char**)PaUtil_GroupAllocateMemory( + result =(char**)PaUtil_GroupAllocateZeroInitializedMemory( group, sizeof(char*) * driverCount ); if( !result ) goto error; - result[0] = (char*)PaUtil_GroupAllocateMemory( + result[0] = (char*)PaUtil_GroupAllocateZeroInitializedMemory( group, 32 * driverCount ); if( !result[0] ) goto error; @@ -942,7 +932,7 @@ PaError PaAsio_GetAvailableBufferSizes( PaDeviceIndex device, */ static void UnloadAsioDriver( void ) { - ASIOExit(); + ASIOExit(); } /* @@ -1005,9 +995,9 @@ static PaError LoadAsioDriver( PaAsioHostApiRepresentation *asioHostApi, const c error: if( asioIsInitialized ) - { - ASIOExit(); - } + { + ASIOExit(); + } return result; } @@ -1019,7 +1009,7 @@ static ASIOSampleRate defaultSampleRateSearchOrder_[] 192000.0, 16000.0, 12000.0, 11025.0, 9600.0, 8000.0 }; -static PaError InitPaDeviceInfoFromAsioDriver( PaAsioHostApiRepresentation *asioHostApi, +static PaError InitPaDeviceInfoFromAsioDriver( PaAsioHostApiRepresentation *asioHostApi, const char *driverName, int driverIndex, PaDeviceInfo *deviceInfo, PaAsioDeviceInfo *asioDeviceInfo ) { @@ -1083,11 +1073,11 @@ static PaError InitPaDeviceInfoFromAsioDriver( PaAsioHostApiRepresentation *asio paAsioDriver.info.bufferMaxSize / deviceInfo->defaultSampleRate; if( defaultHighLatency < defaultLowLatency ) - defaultHighLatency = defaultLowLatency; /* just in case the driver returns something strange */ - + defaultHighLatency = defaultLowLatency; /* just in case the driver returns something strange */ + deviceInfo->defaultHighInputLatency = defaultHighLatency; deviceInfo->defaultHighOutputLatency = defaultHighLatency; - + }else{ deviceInfo->defaultLowInputLatency = 0.; @@ -1107,7 +1097,7 @@ static PaError InitPaDeviceInfoFromAsioDriver( PaAsioHostApiRepresentation *asio asioDeviceInfo->bufferGranularity = paAsioDriver.info.bufferGranularity; - asioDeviceInfo->asioChannelInfos = (ASIOChannelInfo*)PaUtil_GroupAllocateMemory( + asioDeviceInfo->asioChannelInfos = (ASIOChannelInfo*)PaUtil_GroupAllocateZeroInitializedMemory( asioHostApi->allocations, sizeof(ASIOChannelInfo) * (deviceInfo->maxInputChannels + deviceInfo->maxOutputChannels) ); @@ -1174,14 +1164,15 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex PaAsioHostApiRepresentation *asioHostApi; PaAsioDeviceInfo *deviceInfoArray; char **names; - asioHostApi = (PaAsioHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaAsioHostApiRepresentation) ); + asioHostApi = (PaAsioHostApiRepresentation*)PaUtil_AllocateZeroInitializedMemory( sizeof(PaAsioHostApiRepresentation) ); if( !asioHostApi ) { result = paInsufficientMemory; goto error; } - memset( asioHostApi, 0, sizeof(PaAsioHostApiRepresentation) ); /* ensure all fields are zeroed. especially asioHostApi->allocations */ + /* NOTE: we depend on PaUtil_AllocateZeroInitializedMemory() ensuring that all + fields are set to zero. especially asioHostApi->allocations */ /* We initialize COM ourselves here and uninitialize it in Terminate(). @@ -1192,7 +1183,7 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex There used to be code that initialized COM in other situations such as when creating a Stream. This made PA work when calling Pa_CreateStream - from a non-main thread. However we currently consider initialization + from a non-main thread. However we currently consider initialization of COM in non-main threads to be the caller's responsibility. */ result = PaWinUtil_CoInitialize( paASIO, &asioHostApi->comInitializationResult ); @@ -1214,7 +1205,7 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex try { asioHostApi->asioDrivers = new AsioDrivers(); /* invokes CoInitialize(0) in AsioDriverList::AsioDriverList */ - } + } catch (std::bad_alloc) { asioHostApi->asioDrivers = 0; @@ -1264,7 +1255,7 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex /* allocate enough space for all drivers, even if some aren't installed */ - (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( + (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateZeroInitializedMemory( asioHostApi->allocations, sizeof(PaDeviceInfo*) * driverCount ); if( !(*hostApi)->deviceInfos ) { @@ -1273,7 +1264,7 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex } /* allocate all device info structs in a contiguous block */ - deviceInfoArray = (PaAsioDeviceInfo*)PaUtil_GroupAllocateMemory( + deviceInfoArray = (PaAsioDeviceInfo*)PaUtil_GroupAllocateZeroInitializedMemory( asioHostApi->allocations, sizeof(PaAsioDeviceInfo) * driverCount ); if( !deviceInfoArray ) { @@ -1291,7 +1282,7 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex // we face fact that some drivers were not meant for it, drivers which act // like shells on top of REAL drivers, for instance. // so we get duplicate handles, locks and other problems. - // so lets NOT try to load any such wrappers. + // so lets NOT try to load any such wrappers. // The ones i [davidv] know of so far are: if ( strcmp (names[i],"ASIO DirectX Full Duplex Driver") == 0 @@ -1305,16 +1296,16 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex } - if( IsDebuggerPresent_ && IsDebuggerPresent_() ) + if( IsDebuggerPresent_ && IsDebuggerPresent_() ) { /* ASIO Digidesign Driver uses PACE copy protection which quits out if a debugger is running. So we don't load it if a debugger is running. */ - if( strcmp(names[i], "ASIO Digidesign Driver") == 0 ) + if( strcmp(names[i], "ASIO Digidesign Driver") == 0 ) { - PA_DEBUG(("BLACKLISTED!!! ASIO Digidesign Driver would quit the debugger\n")); + PA_DEBUG(("BLACKLISTED!!! ASIO Digidesign Driver would quit the debugger\n")); continue; - } - } + } + } /* Attempt to init device info from the asio driver... */ @@ -1332,8 +1323,8 @@ PaError PaAsio_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex (*hostApi)->deviceInfos[ (*hostApi)->info.deviceCount ] = deviceInfo; ++(*hostApi)->info.deviceCount; } - else - { + else + { PA_DEBUG(("Skipping ASIO device:%s\n",names[i])); continue; } @@ -1425,9 +1416,9 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, PaAsioDriverInfo *driverInfo = &asioHostApi->openAsioDriverInfo; int inputChannelCount, outputChannelCount; PaSampleFormat inputSampleFormat, outputSampleFormat; - PaDeviceIndex asioDeviceIndex; + PaDeviceIndex asioDeviceIndex; ASIOError asioError; - + if( inputParameters && outputParameters ) { /* full duplex ASIO stream must use the same device for input and output */ @@ -1435,7 +1426,7 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, if( inputParameters->device != outputParameters->device ) return paBadIODeviceCombination; } - + if( inputParameters ) { inputChannelCount = inputParameters->channelCount; @@ -1445,7 +1436,7 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, this implementation doesn't support any custom sample formats */ if( inputSampleFormat & paCustomFormat ) return paSampleFormatNotSupported; - + /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ @@ -1473,7 +1464,7 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, this implementation doesn't support any custom sample formats */ if( outputSampleFormat & paCustomFormat ) return paSampleFormatNotSupported; - + /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ @@ -1496,7 +1487,7 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, /* if an ASIO device is open we can only get format information for the currently open device */ - if( asioHostApi->openAsioDeviceIndex != paNoDevice + if( asioHostApi->openAsioDeviceIndex != paNoDevice && asioHostApi->openAsioDeviceIndex != asioDeviceIndex ) { return paDeviceUnavailable; @@ -1534,7 +1525,7 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, goto done; } } - + /* query for sample rate support */ asioError = ASIOCanSampleRate( sampleRate ); if( asioError == ASE_NoClock || asioError == ASE_NotPresent ) @@ -1659,9 +1650,9 @@ static void ZeroOutputBuffers( PaAsioStream *stream, long index ) } -/* return the next power of two >= x. - Returns the input parameter if it is already a power of two. - http://stackoverflow.com/questions/364985/algorithm-for-finding-the-smallest-power-of-two-thats-greater-or-equal-to-a-giv +/* return the next power of two >= x. + Returns the input parameter if it is already a power of two. + http://stackoverflow.com/questions/364985/algorithm-for-finding-the-smallest-power-of-two-thats-greater-or-equal-to-a-giv */ static unsigned long NextPowerOfTwo( unsigned long x ) { @@ -1671,8 +1662,8 @@ static unsigned long NextPowerOfTwo( unsigned long x ) x |= x >> 4; x |= x >> 8; x |= x >> 16; - /* If you needed to deal with numbers > 2^32 the following would be needed. - For latencies, we don't deal with values this large. + /* If you needed to deal with numbers > 2^32 the following would be needed. + For latencies, we don't deal with values this large. x |= x >> 16; */ @@ -1680,16 +1671,16 @@ static unsigned long NextPowerOfTwo( unsigned long x ) } -static unsigned long SelectHostBufferSizeForUnspecifiedUserFramesPerBuffer( +static unsigned long SelectHostBufferSizeForUnspecifiedUserFramesPerBuffer( unsigned long targetBufferingLatencyFrames, PaAsioDriverInfo *driverInfo ) { - /* Choose a host buffer size based only on targetBufferingLatencyFrames and the - device's supported buffer sizes. Always returns a valid value. - */ + /* Choose a host buffer size based only on targetBufferingLatencyFrames and the + device's supported buffer sizes. Always returns a valid value. + */ - unsigned long result; + unsigned long result; - if( targetBufferingLatencyFrames <= (unsigned long)driverInfo->bufferMinSize ) + if( targetBufferingLatencyFrames <= (unsigned long)driverInfo->bufferMinSize ) { result = driverInfo->bufferMinSize; } @@ -1699,18 +1690,18 @@ static unsigned long SelectHostBufferSizeForUnspecifiedUserFramesPerBuffer( } else { - if( driverInfo->bufferGranularity == 0 ) /* single fixed host buffer size */ + if( driverInfo->bufferGranularity == 0 ) /* single fixed host buffer size */ { - /* The documentation states that bufferGranularity should be zero - when bufferMinSize, bufferMaxSize and bufferPreferredSize are the + /* The documentation states that bufferGranularity should be zero + when bufferMinSize, bufferMaxSize and bufferPreferredSize are the same. We assume that is the case. */ result = driverInfo->bufferPreferredSize; } - else if( driverInfo->bufferGranularity == -1 ) /* power-of-two */ + else if( driverInfo->bufferGranularity == -1 ) /* power-of-two */ { - /* We assume bufferMinSize and bufferMaxSize are powers of two. */ + /* We assume bufferMinSize and bufferMaxSize are powers of two. */ result = NextPowerOfTwo( targetBufferingLatencyFrames ); @@ -1723,9 +1714,9 @@ static unsigned long SelectHostBufferSizeForUnspecifiedUserFramesPerBuffer( else /* modulo bufferGranularity */ { /* round up to the next multiple of granularity */ - unsigned long n = (targetBufferingLatencyFrames + driverInfo->bufferGranularity - 1) + unsigned long n = (targetBufferingLatencyFrames + driverInfo->bufferGranularity - 1) / driverInfo->bufferGranularity; - + result = n * driverInfo->bufferGranularity; if( result < (unsigned long)driverInfo->bufferMinSize ) @@ -1736,137 +1727,137 @@ static unsigned long SelectHostBufferSizeForUnspecifiedUserFramesPerBuffer( } } - return result; + return result; } -static unsigned long SelectHostBufferSizeForSpecifiedUserFramesPerBuffer( +static unsigned long SelectHostBufferSizeForSpecifiedUserFramesPerBuffer( unsigned long targetBufferingLatencyFrames, unsigned long userFramesPerBuffer, PaAsioDriverInfo *driverInfo ) { - /* Select a host buffer size conforming to targetBufferingLatencyFrames - and the device's supported buffer sizes. - The return value will always be a multiple of userFramesPerBuffer. - If a valid buffer size can not be found the function returns 0. - - The current implementation uses a simple iterative search for clarity. - Feel free to suggest a closed form solution. - */ - unsigned long result = 0; - - assert( userFramesPerBuffer != 0 ); - - if( driverInfo->bufferGranularity == 0 ) /* single fixed host buffer size */ + /* Select a host buffer size conforming to targetBufferingLatencyFrames + and the device's supported buffer sizes. + The return value will always be a multiple of userFramesPerBuffer. + If a valid buffer size can not be found the function returns 0. + + The current implementation uses a simple iterative search for clarity. + Feel free to suggest a closed form solution. + */ + unsigned long result = 0; + + assert( userFramesPerBuffer != 0 ); + + if( driverInfo->bufferGranularity == 0 ) /* single fixed host buffer size */ { - /* The documentation states that bufferGranularity should be zero - when bufferMinSize, bufferMaxSize and bufferPreferredSize are the + /* The documentation states that bufferGranularity should be zero + when bufferMinSize, bufferMaxSize and bufferPreferredSize are the same. We assume that is the case. */ - if( (driverInfo->bufferPreferredSize % userFramesPerBuffer) == 0 ) - result = driverInfo->bufferPreferredSize; + if( (driverInfo->bufferPreferredSize % userFramesPerBuffer) == 0 ) + result = driverInfo->bufferPreferredSize; } - else if( driverInfo->bufferGranularity == -1 ) /* power-of-two */ + else if( driverInfo->bufferGranularity == -1 ) /* power-of-two */ { - /* We assume bufferMinSize and bufferMaxSize are powers of two. */ + /* We assume bufferMinSize and bufferMaxSize are powers of two. */ - /* Search all powers of two in the range [bufferMinSize,bufferMaxSize] + /* Search all powers of two in the range [bufferMinSize,bufferMaxSize] for multiples of userFramesPerBuffer. We prefer the first multiple - that is equal or greater than targetBufferingLatencyFrames, or - failing that, the largest multiple less than + that is equal or greater than targetBufferingLatencyFrames, or + failing that, the largest multiple less than targetBufferingLatencyFrames. */ - unsigned long x = (unsigned long)driverInfo->bufferMinSize; - do { - if( (x % userFramesPerBuffer) == 0 ) - { + unsigned long x = (unsigned long)driverInfo->bufferMinSize; + do { + if( (x % userFramesPerBuffer) == 0 ) + { /* any multiple of userFramesPerBuffer is acceptable */ - result = x; - if( result >= targetBufferingLatencyFrames ) - break; /* stop. a value >= to targetBufferingLatencyFrames is ideal. */ - } + result = x; + if( result >= targetBufferingLatencyFrames ) + break; /* stop. a value >= to targetBufferingLatencyFrames is ideal. */ + } - x *= 2; - } while( x <= (unsigned long)driverInfo->bufferMaxSize ); + x *= 2; + } while( x <= (unsigned long)driverInfo->bufferMaxSize ); } else /* modulo granularity */ { - /* We assume bufferMinSize is a multiple of bufferGranularity. */ + /* We assume bufferMinSize is a multiple of bufferGranularity. */ - /* Search all multiples of bufferGranularity in the range - [bufferMinSize,bufferMaxSize] for multiples of userFramesPerBuffer. - We prefer the first multiple that is equal or greater than - targetBufferingLatencyFrames, or failing that, the largest multiple + /* Search all multiples of bufferGranularity in the range + [bufferMinSize,bufferMaxSize] for multiples of userFramesPerBuffer. + We prefer the first multiple that is equal or greater than + targetBufferingLatencyFrames, or failing that, the largest multiple less than targetBufferingLatencyFrames. */ - unsigned long x = (unsigned long)driverInfo->bufferMinSize; - do { - if( (x % userFramesPerBuffer) == 0 ) - { + unsigned long x = (unsigned long)driverInfo->bufferMinSize; + do { + if( (x % userFramesPerBuffer) == 0 ) + { /* any multiple of userFramesPerBuffer is acceptable */ - result = x; - if( result >= targetBufferingLatencyFrames ) - break; /* stop. a value >= to targetBufferingLatencyFrames is ideal. */ - } + result = x; + if( result >= targetBufferingLatencyFrames ) + break; /* stop. a value >= to targetBufferingLatencyFrames is ideal. */ + } - x += driverInfo->bufferGranularity; - } while( x <= (unsigned long)driverInfo->bufferMaxSize ); + x += driverInfo->bufferGranularity; + } while( x <= (unsigned long)driverInfo->bufferMaxSize ); } - return result; + return result; } -static unsigned long SelectHostBufferSize( - unsigned long targetBufferingLatencyFrames, +static unsigned long SelectHostBufferSize( + unsigned long targetBufferingLatencyFrames, unsigned long userFramesPerBuffer, PaAsioDriverInfo *driverInfo ) { unsigned long result = 0; - /* We select a host buffer size based on the following requirements + /* We select a host buffer size based on the following requirements (in priority order): - 1. The host buffer size must be permissible according to the ASIO - driverInfo buffer size constraints (min, max, granularity or + 1. The host buffer size must be permissible according to the ASIO + driverInfo buffer size constraints (min, max, granularity or powers-of-two). - 2. If the user specifies a non-zero framesPerBuffer parameter - (userFramesPerBuffer here) the host buffer should be a multiple of + 2. If the user specifies a non-zero framesPerBuffer parameter + (userFramesPerBuffer here) the host buffer should be a multiple of this (subject to the constraints in (1) above). - [NOTE: Where no permissible host buffer size is a multiple of - userFramesPerBuffer, we choose a value as if userFramesPerBuffer were - zero (i.e. we ignore it). This strategy is open for review ~ perhaps - there are still "more optimal" buffer sizes related to + [NOTE: Where no permissible host buffer size is a multiple of + userFramesPerBuffer, we choose a value as if userFramesPerBuffer were + zero (i.e. we ignore it). This strategy is open for review ~ perhaps + there are still "more optimal" buffer sizes related to userFramesPerBuffer that we could use.] - 3. The host buffer size should be greater than or equal to - targetBufferingLatencyFrames, subject to (1) and (2) above. Where it - is not possible to select a host buffer size equal or greater than - targetBufferingLatencyFrames, the highest buffer size conforming to + 3. The host buffer size should be greater than or equal to + targetBufferingLatencyFrames, subject to (1) and (2) above. Where it + is not possible to select a host buffer size equal or greater than + targetBufferingLatencyFrames, the highest buffer size conforming to (1) and (2) should be chosen. */ - if( userFramesPerBuffer != 0 ) - { - /* userFramesPerBuffer is specified, try to find a buffer size that's + if( userFramesPerBuffer != 0 ) + { + /* userFramesPerBuffer is specified, try to find a buffer size that's a multiple of it */ - result = SelectHostBufferSizeForSpecifiedUserFramesPerBuffer( + result = SelectHostBufferSizeForSpecifiedUserFramesPerBuffer( targetBufferingLatencyFrames, userFramesPerBuffer, driverInfo ); - } + } - if( result == 0 ) - { - /* either userFramesPerBuffer was not specified, or we couldn't find a - host buffer size that is a multiple of it. Select a host buffer size - according to targetBufferingLatencyFrames and the ASIO driverInfo + if( result == 0 ) + { + /* either userFramesPerBuffer was not specified, or we couldn't find a + host buffer size that is a multiple of it. Select a host buffer size + according to targetBufferingLatencyFrames and the ASIO driverInfo buffer size constraints. - */ - result = SelectHostBufferSizeForUnspecifiedUserFramesPerBuffer( + */ + result = SelectHostBufferSizeForUnspecifiedUserFramesPerBuffer( targetBufferingLatencyFrames, driverInfo ); - } + } - return result; + return result; } @@ -1893,10 +1884,10 @@ static PaError ValidateAsioSpecificStreamInfo( return paIncompatibleHostApiSpecificStreamInfo; for( int i=0; i < streamParameters->channelCount; ++i ){ - if( (*channelSelectors)[i] < 0 + if( (*channelSelectors)[i] < 0 || (*channelSelectors)[i] >= deviceChannelCount ){ return paInvalidChannelCount; - } + } } } @@ -1914,7 +1905,7 @@ static bool IsUsingExternalClockSource() /* davidv: listing ASIO Clock sources. there is an ongoing investigation by me about whether or not to call ASIOSetSampleRate if an external Clock is used. A few drivers expected different things here */ - + asioError = ASIOGetClockSources(clocks, &numSources); if( asioError != ASE_OK ){ PA_DEBUG(("ERROR: ASIOGetClockSources: %s\n", PaAsio_GetAsioErrorText(asioError) )); @@ -1922,7 +1913,7 @@ static bool IsUsingExternalClockSource() PA_DEBUG(("INFO ASIOGetClockSources listing %d clocks\n", numSources )); for (int i=0;icpuLoadMeasurer, sampleRate ); - stream->asioBufferInfos = (ASIOBufferInfo*)PaUtil_AllocateMemory( + stream->asioBufferInfos = (ASIOBufferInfo*)PaUtil_AllocateZeroInitializedMemory( sizeof(ASIOBufferInfo) * (inputChannelCount + outputChannelCount) ); if( !stream->asioBufferInfos ) { @@ -2257,7 +2248,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, }else{ info->channelNum = i; } - + info->buffers[0] = info->buffers[1] = 0; } @@ -2273,14 +2264,14 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, else /* Using callback interface... */ { /* Select the host buffer size based on user framesPerBuffer and the - maximum of suggestedInputLatencyFrames and + maximum of suggestedInputLatencyFrames and suggestedOutputLatencyFrames. - We should subtract any fixed known driver latency from + We should subtract any fixed known driver latency from suggestedLatencyFrames before computing the host buffer size. - However, the ASIO API doesn't provide a method for determining fixed - latencies independent of the host buffer size. ASIOGetLatencies() - only returns latencies after the buffer size has been configured, so + However, the ASIO API doesn't provide a method for determining fixed + latencies independent of the host buffer size. ASIOGetLatencies() + only returns latencies after the buffer size has been configured, so we can't reliably use it to determine fixed latencies here. We could set the preferred buffer size and then subtract it from @@ -2288,12 +2279,12 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, reliable, so we don't do it. */ - unsigned long targetBufferingLatencyFrames = + unsigned long targetBufferingLatencyFrames = (( suggestedInputLatencyFrames > suggestedOutputLatencyFrames ) - ? suggestedInputLatencyFrames + ? suggestedInputLatencyFrames : suggestedOutputLatencyFrames); - framesPerHostBuffer = SelectHostBufferSize( targetBufferingLatencyFrames, + framesPerHostBuffer = SelectHostBufferSize( targetBufferingLatencyFrames, framesPerBuffer, driverInfo ); } @@ -2336,7 +2327,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, asioBuffersCreated = 1; - stream->asioChannelInfos = (ASIOChannelInfo*)PaUtil_AllocateMemory( + stream->asioChannelInfos = (ASIOChannelInfo*)PaUtil_AllocateZeroInitializedMemory( sizeof(ASIOChannelInfo) * (inputChannelCount + outputChannelCount) ); if( !stream->asioChannelInfos ) { @@ -2359,7 +2350,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, } } - stream->bufferPtrs = (void**)PaUtil_AllocateMemory( + stream->bufferPtrs = (void**)PaUtil_AllocateZeroInitializedMemory( 2 * sizeof(void*) * (inputChannelCount + outputChannelCount) ); if( !stream->bufferPtrs ) { @@ -2404,8 +2395,8 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, if( inputChannelCount > 0 ) { - /* FIXME: assume all channels use the same type for now - + /* FIXME: assume all channels use the same type for now + see: "ASIO devices with multiple sample formats are unsupported" http://www.portaudio.com/trac/ticket/106 */ @@ -2425,8 +2416,8 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, if( outputChannelCount > 0 ) { - /* FIXME: assume all channels use the same type for now - + /* FIXME: assume all channels use the same type for now + see: "ASIO devices with multiple sample formats are unsupported" http://www.portaudio.com/trac/ticket/106 */ @@ -2444,7 +2435,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, stream->outputBufferConverter = 0; } - /* Values returned by ASIOGetLatencies() include the latency introduced by + /* Values returned by ASIOGetLatencies() include the latency introduced by the ASIO double buffer. */ ASIOGetLatencies( &stream->asioInputLatencyFrames, &stream->asioOutputLatencyFrames ); @@ -2453,7 +2444,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, if( usingBlockingIo ) { /* Allocate the blocking i/o input ring buffer memory. */ - stream->blockingState = (PaAsioStreamBlockingState*)PaUtil_AllocateMemory( sizeof(PaAsioStreamBlockingState) ); + stream->blockingState = (PaAsioStreamBlockingState*)PaUtil_AllocateZeroInitializedMemory( sizeof(PaAsioStreamBlockingState) ); if( !stream->blockingState ) { result = paInsufficientMemory; @@ -2536,7 +2527,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, /* Create pointer buffer to access non-interleaved data in ReadStream() */ - stream->blockingState->readStreamBuffer = (void**)PaUtil_AllocateMemory( sizeof(void*) * inputChannelCount ); + stream->blockingState->readStreamBuffer = (void**)PaUtil_AllocateZeroInitializedMemory( sizeof(void*) * inputChannelCount ); if( !stream->blockingState->readStreamBuffer ) { result = paInsufficientMemory; @@ -2549,7 +2540,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, enough to store at least two complete data blocks. 1) Determine the amount of latency to be added to the - prefered ASIO latency. + preferred ASIO latency. 2) Make sure we have at lest one additional latency frame. 3) Divide the number of frames by the desired block size to get the number (rounded up to pure integer) of blocks to @@ -2568,7 +2559,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, while( lBlockingBufferSize > (lBlockingBufferSizePow2<<=1) ); lBlockingBufferSize = lBlockingBufferSizePow2; - /* Compute total intput latency in seconds */ + /* Compute total input latency in seconds */ stream->streamRepresentation.streamInfo.inputLatency = (double)( PaUtil_GetBufferProcessorInputLatencyFrames(&stream->bufferProcessor ) + PaUtil_GetBufferProcessorInputLatencyFrames(&stream->blockingState->bufferProcessor) @@ -2593,7 +2584,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, lBytesPerFrame = inputChannelCount * Pa_GetSampleSize(inputSampleFormat ); /* Allocate the blocking i/o input ring buffer memory. */ - stream->blockingState->readRingBufferData = (void*)PaUtil_AllocateMemory( lBlockingBufferSize * lBytesPerFrame ); + stream->blockingState->readRingBufferData = (void*)PaUtil_AllocateZeroInitializedMemory( lBlockingBufferSize * lBytesPerFrame ); if( !stream->blockingState->readRingBufferData ) { result = paInsufficientMemory; @@ -2622,7 +2613,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, blockingWriteBuffersReadyEventInitialized = 1; /* Create pointer buffer to access non-interleaved data in WriteStream() */ - stream->blockingState->writeStreamBuffer = (const void**)PaUtil_AllocateMemory( sizeof(const void*) * outputChannelCount ); + stream->blockingState->writeStreamBuffer = (const void**)PaUtil_AllocateZeroInitializedMemory( sizeof(const void*) * outputChannelCount ); if( !stream->blockingState->writeStreamBuffer ) { result = paInsufficientMemory; @@ -2635,7 +2626,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, enough to store at least two complete data blocks. 1) Determine the amount of latency to be added to the - prefered ASIO latency. + preferred ASIO latency. 2) Make sure we have at lest one additional latency frame. 3) Divide the number of frames by the desired block size to get the number (rounded up to pure integer) of blocks to @@ -2684,7 +2675,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, lBytesPerFrame = outputChannelCount * Pa_GetSampleSize(outputSampleFormat); /* Allocate the blocking i/o output ring buffer memory. */ - stream->blockingState->writeRingBufferData = (void*)PaUtil_AllocateMemory( lBlockingBufferSize * lBytesPerFrame ); + stream->blockingState->writeRingBufferData = (void*)PaUtil_AllocateZeroInitializedMemory( lBlockingBufferSize * lBytesPerFrame ); if( !stream->blockingState->writeRingBufferData ) { result = paInsufficientMemory; @@ -2729,14 +2720,14 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, // buffer processor latency. it reports the added latency separately PA_DEBUG(("PaAsio : ASIO InputLatency = %ld (%ld ms), added buffProc:%ld (%ld ms)\n", stream->asioInputLatencyFrames, - (long)((stream->asioInputLatencyFrames*1000)/ sampleRate), + (long)((stream->asioInputLatencyFrames*1000)/ sampleRate), PaUtil_GetBufferProcessorInputLatencyFrames(&stream->bufferProcessor), (long)((PaUtil_GetBufferProcessorInputLatencyFrames(&stream->bufferProcessor)*1000)/ sampleRate) )); PA_DEBUG(("PaAsio : ASIO OuputLatency = %ld (%ld ms), added buffProc:%ld (%ld ms)\n", stream->asioOutputLatencyFrames, - (long)((stream->asioOutputLatencyFrames*1000)/ sampleRate), + (long)((stream->asioOutputLatencyFrames*1000)/ sampleRate), PaUtil_GetBufferProcessorOutputLatencyFrames(&stream->bufferProcessor), (long)((PaUtil_GetBufferProcessorOutputLatencyFrames(&stream->bufferProcessor)*1000)/ sampleRate) )); @@ -2750,7 +2741,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, stream->postOutput = driverInfo->postOutput; stream->isStopped = 1; stream->isActive = 0; - + asioHostApi->openAsioDeviceIndex = asioDeviceIndex; theAsioStream = stream; @@ -2806,9 +2797,9 @@ error: ASIODisposeBuffers(); if( asioIsInitialized ) - { - UnloadAsioDriver(); - } + { + UnloadAsioDriver(); + } return result; } @@ -2872,7 +2863,7 @@ static void bufferSwitch(long index, ASIOBool directProcess) //TAKEN FROM THE ASIO SDK // the actual processing callback. - // Beware that this is normally in a seperate thread, hence be sure that + // Beware that this is normally in a separate thread, hence be sure that // you take care about thread synchronization. This is omitted here for // simplicity. @@ -2904,7 +2895,7 @@ static void bufferSwitch(long index, ASIOBool directProcess) static ASIOTime *bufferSwitchTimeInfo( ASIOTime *timeInfo, long index, ASIOBool directProcess ) { // the actual processing callback. - // Beware that this is normally in a seperate thread, hence be sure that + // Beware that this is normally in a separate thread, hence be sure that // you take care about thread synchronization. @@ -2972,17 +2963,17 @@ static ASIOTime *bufferSwitchTimeInfo( ASIOTime *timeInfo, long index, ASIOBool } int buffersDone = 0; - + do { if( buffersDone > 0 ) { // this is a reentered buffer, we missed processing it on time // set the input overflow and output underflow flags as appropriate - + if( theAsioStream->inputChannelCount > 0 ) theAsioStream->callbackFlags |= paInputOverflow; - + if( theAsioStream->outputChannelCount > 0 ) theAsioStream->callbackFlags |= paOutputUnderflow; } @@ -3177,7 +3168,7 @@ previousTime = paTimeInfo.currentTime; } } } - + ++buffersDone; }while( PaAsio_AtomicDecrement(&theAsioStream->reenterCount) >= 0 ); @@ -3269,7 +3260,7 @@ static long asioMessages(long selector, long value, void* message, double* opt) break; case kAsioSupportsTimeInfo: - // informs the driver wether the asioCallbacks.bufferSwitchTimeInfo() callback + // informs the driver whether the asioCallbacks.bufferSwitchTimeInfo() callback // is supported. // For compatibility with ASIO 1.0 drivers the host application should always support // the "old" bufferSwitch method, too. @@ -3277,7 +3268,7 @@ static long asioMessages(long selector, long value, void* message, double* opt) break; case kAsioSupportsTimeCode: - // informs the driver wether application is interested in time code info. + // informs the driver whether application is interested in time code info. // If an application does not need to know about time code, the driver has less work // to do. ret = 0; @@ -3423,7 +3414,7 @@ static PaError StopStream( PaStream *s ) blockingState->stopFlag = TRUE; /* Wait until requested number of buffers has been freed. Time - out after twice the blocking i/o ouput buffer could have + out after twice the blocking i/o output buffer could have been consumed. */ DWORD timeout = (DWORD)( 2 * blockingState->writeRingBuffer.bufferSize * 1000 / stream->streamRepresentation.streamInfo.sampleRate ); @@ -3518,7 +3509,7 @@ static PaError AbortStream( PaStream *s ) static PaError IsStreamStopped( PaStream *s ) { PaAsioStream *stream = (PaAsioStream*)s; - + return stream->isStopped; } @@ -3677,7 +3668,7 @@ static PaError ReadStream( PaStream *s , &lRingBufferSize2nd); /* Set number of frames to be copied from the ring buffer. */ - PaUtil_SetInputFrameCount( pBp, lRingBufferSize1st ); + PaUtil_SetInputFrameCount( pBp, lRingBufferSize1st ); /* Setup ring buffer access. */ PaUtil_SetInterleavedInputChannels(pBp , /* Buffer processor. */ 0 , /* The first channel's index. */ @@ -3762,7 +3753,7 @@ static PaError WriteStream( PaStream *s , unsigned int i; /* Just a counter. */ - /* Check if the stream ist still available ready to recieve new data. */ + /* Check if the stream is still available ready to receive new data. */ if( blockingState->stopFlag || !stream->isActive ) { PA_DEBUG(("Warning! Stream no longer available for writing in WriteStream()\n")); @@ -3824,7 +3815,7 @@ static PaError WriteStream( PaStream *s , /* If block processing has stopped, abort! */ if( blockingState->stopFlag ) { return result = paStreamIsStopped; } - + /* If a timeout is encountered, give up eventually. */ return result = paTimedOut; } @@ -3849,7 +3840,7 @@ static PaError WriteStream( PaStream *s , &lRingBufferSize2nd); /* Set number of frames to be copied to the ring buffer. */ - PaUtil_SetOutputFrameCount( pBp, lRingBufferSize1st ); + PaUtil_SetOutputFrameCount( pBp, lRingBufferSize1st ); /* Setup ring buffer access. */ PaUtil_SetInterleavedOutputChannels(pBp , /* Buffer processor. */ 0 , /* The first channel's index. */ @@ -4093,10 +4084,10 @@ PaError PaAsio_ShowControlPanel( PaDeviceIndex device, void* systemSpecific ) } PA_DEBUG(("PaAsio_ShowControlPanel: ASIOInit(): %s\n", PaAsio_GetAsioErrorText(asioError) )); -PA_DEBUG(("asioVersion: ASIOInit(): %ld\n", asioDriverInfo.asioVersion )); -PA_DEBUG(("driverVersion: ASIOInit(): %ld\n", asioDriverInfo.driverVersion )); -PA_DEBUG(("Name: ASIOInit(): %s\n", asioDriverInfo.name )); -PA_DEBUG(("ErrorMessage: ASIOInit(): %s\n", asioDriverInfo.errorMessage )); +PA_DEBUG(("asioVersion: ASIOInit(): %ld\n", asioDriverInfo.asioVersion )); +PA_DEBUG(("driverVersion: ASIOInit(): %ld\n", asioDriverInfo.driverVersion )); +PA_DEBUG(("Name: ASIOInit(): %s\n", asioDriverInfo.name )); +PA_DEBUG(("ErrorMessage: ASIOInit(): %s\n", asioDriverInfo.errorMessage )); asioError = ASIOControlPanel(); if( asioError != ASE_OK ) @@ -4124,9 +4115,9 @@ PA_DEBUG(("PaAsio_ShowControlPanel: ASIOExit(): %s\n", PaAsio_GetAsioErrorText(a error: if( asioIsInitialized ) - { - ASIOExit(); - } + { + ASIOExit(); + } PaWinUtil_CoUninitialize( paASIO, &comInitializationResult ); @@ -4161,7 +4152,7 @@ PaError PaAsio_GetInputChannelName( PaDeviceIndex device, int channelIndex, *channelName = asioDeviceInfo->asioChannelInfos[channelIndex].name; return paNoError; - + error: return result; } @@ -4195,7 +4186,7 @@ PaError PaAsio_GetOutputChannelName( PaDeviceIndex device, int channelIndex, asioDeviceInfo->commonDeviceInfo.maxInputChannels + channelIndex].name; return paNoError; - + error: return result; } @@ -4211,7 +4202,7 @@ static PaError GetAsioStreamPointer( PaAsioStream **stream, PaStream *s ) PaError result; PaUtilHostApiRepresentation *hostApi; PaAsioHostApiRepresentation *asioHostApi; - + result = PaUtil_ValidateStreamPointer( s ); if( result != paNoError ) return result; @@ -4221,7 +4212,7 @@ static PaError GetAsioStreamPointer( PaAsioStream **stream, PaStream *s ) return result; asioHostApi = (PaAsioHostApiRepresentation*)hostApi; - + if( PA_STREAM_REP( s )->streamInterface == &asioHostApi->callbackStreamInterface || PA_STREAM_REP( s )->streamInterface == &asioHostApi->blockingStreamInterface ) { @@ -4248,4 +4239,3 @@ PaError PaAsio_SetStreamSampleRate( PaStream* s, double sampleRate ) return ValidateAndSetSampleRate( sampleRate ); } - diff --git a/3rdparty/portaudio/src/hostapi/audioio/pa_unix_audioio.c b/3rdparty/portaudio/src/hostapi/audioio/pa_unix_audioio.c new file mode 100644 index 00000000000..965186ac86b --- /dev/null +++ b/3rdparty/portaudio/src/hostapi/audioio/pa_unix_audioio.c @@ -0,0 +1,1121 @@ +/* + * $Id$ + * PortAudio Portable Real-Time Audio Library + * Latest Version at: http://www.portaudio.com + * Solaris/NetBSD implementation by: + * Nia Alarie + * + * 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 hostapi_src +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "pa_util.h" +#include "pa_unix_util.h" +#include "pa_debugprint.h" +#include "pa_allocation.h" +#include "pa_hostapi.h" +#include "pa_stream.h" +#include "pa_cpuload.h" +#include "pa_process.h" + +#ifndef AUDIOIO_MAX_DEVICES +#define AUDIOIO_MAX_DEVICES (32) +#endif + +#ifndef AUDIOIO_DEFAULT_FRAMES +#define AUDIOIO_DEFAULT_FRAMES (128) +#endif + +#ifndef AUDIOIO_DEFAULT_MAX_CHANNELS +# ifdef __NetBSD__ +# define AUDIOIO_DEFAULT_MAX_CHANNELS (12) +# else +# define AUDIOIO_DEFAULT_MAX_CHANNELS (2) +# endif +#endif + +#ifndef AUDIOIO_DEV_PREFIX +# ifdef __sun +# define AUDIOIO_DEV_PREFIX "/dev/sound/" +# else +# define AUDIOIO_DEV_PREFIX "/dev/audio" +# endif +#endif + +#ifndef AUDIOIO_DEV_DEFAULT +#define AUDIOIO_DEV_DEFAULT "/dev/audio" +#endif + +#ifndef AUDIO_ENCODING_SLINEAR +#define AUDIO_ENCODING_SLINEAR AUDIO_ENCODING_LINEAR +#endif + +// AUDIO_GETBUFINFO is simply an optimization +#ifndef AUDIO_GETBUFINFO +#define AUDIO_GETBUFINFO AUDIO_GETINFO +#endif + +PaError PaAudioIO_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index ); +static void Terminate( struct PaUtilHostApiRepresentation *hostApi ); +static bool AttemptEncoding( int fd, int encoding, int precision, bool record ); +static PaSampleFormat GetSupportedEncodings( int fd, bool record ); +static PaError PaFormatToAudioIOFormat( PaSampleFormat fmt, struct audio_prinfo *info ); +static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, + const PaStreamParameters *inputParameters, + const PaStreamParameters *outputParameters, + double sampleRate ); +static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, + PaStream** s, + const PaStreamParameters *inputParameters, + const PaStreamParameters *outputParameters, + double sampleRate, + unsigned long framesPerBuffer, + PaStreamFlags streamFlags, + PaStreamCallback *streamCallback, + void *userData ); +static PaError CloseStream( PaStream* stream ); +static PaError StartStream( PaStream *stream ); +static PaError StopStream( PaStream *stream ); +static PaError AbortStream( PaStream *stream ); +static PaError IsStreamStopped( PaStream *s ); +static PaError IsStreamActive( PaStream *stream ); +static PaTime GetStreamTime( PaStream *stream ); +static double GetStreamCpuLoad( PaStream* stream ); +static PaError ReadStream( PaStream* stream, void *buffer, unsigned long frames ); +static PaError WriteStream( PaStream* stream, const void *buffer, unsigned long frames ); +static signed long GetStreamReadAvailable( PaStream* stream ); +static signed long GetStreamWriteAvailable( PaStream* stream ); + +/* PaAudioIOHostApiRepresentation - host api datastructure specific to this implementation */ + +typedef struct +{ + PaUtilHostApiRepresentation inheritedHostApiRep; + PaUtilStreamInterface callbackStreamInterface; + PaUtilStreamInterface blockingStreamInterface; + PaUtilAllocationGroup *allocations; +} +PaAudioIOHostApiRepresentation; + + +PaError PaAudioIO_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex ) +{ + PaError result = paNoError; + int fd = -1, i, deviceCount = 0; + PaAudioIOHostApiRepresentation *audioIOHostApi; + PaUtilHostApiRepresentation *common; + + PA_UNLESS( audioIOHostApi = calloc(1, sizeof(PaAudioIOHostApiRepresentation)), paInsufficientMemory ); + + common = &audioIOHostApi->inheritedHostApiRep; + common->info.structVersion = 1; + common->info.type = paAudioIO; + common->info.name = "AudioIO"; + + common->Terminate = Terminate; + common->OpenStream = OpenStream; + common->IsFormatSupported = IsFormatSupported; + + common->info.defaultInputDevice = + common->info.defaultOutputDevice = paNoDevice; + + PA_UNLESS( audioIOHostApi->allocations = PaUtil_CreateAllocationGroup(), paInsufficientMemory ); + + if( (common->deviceInfos = PaUtil_GroupAllocateZeroInitializedMemory( + audioIOHostApi->allocations, sizeof(PaDeviceInfo *) * AUDIOIO_MAX_DEVICES)) == NULL ) + { + result = paInsufficientMemory; + goto error; + } + + for( i=0; i < AUDIOIO_MAX_DEVICES; ++i ) + { + PaDeviceInfo *dev; + struct audio_info hwfmt, info; + char path[16]; + int props; + + if( i > 0 ) + (void)snprintf(path, sizeof(path), AUDIOIO_DEV_PREFIX "%d", i - 1); + else + (void)snprintf(path, sizeof(path), AUDIOIO_DEV_DEFAULT); + + fd = open(path, O_WRONLY | O_NONBLOCK); + if (fd < 0) + fd = open(path, O_RDONLY | O_NONBLOCK); + if (fd < 0) + continue; + + PA_UNLESS(dev = PaUtil_GroupAllocateZeroInitializedMemory(audioIOHostApi->allocations, sizeof(PaDeviceInfo)), paInsufficientMemory); + + dev->structVersion = 2; + dev->hostApi = hostApiIndex; + + PA_UNLESS(dev->name = PaUtil_GroupAllocateZeroInitializedMemory(audioIOHostApi->allocations, sizeof(path)), paInsufficientMemory); + + memcpy((char *)dev->name, path, sizeof(path)); + + dev->defaultSampleRate = 48000.; + + dev->maxInputChannels = dev->maxOutputChannels = AUDIOIO_DEFAULT_MAX_CHANNELS; + + dev->defaultLowInputLatency = + dev->defaultLowOutputLatency = + dev->defaultHighInputLatency = + dev->defaultHighOutputLatency = .04; + +#ifdef AUDIO_GETFORMAT + if( ioctl(fd, AUDIO_GETFORMAT, &hwfmt) != -1 ) + { + if( dev->maxInputChannels > hwfmt.record.channels ) + dev->maxInputChannels = hwfmt.record.channels; + if( dev->maxOutputChannels > hwfmt.play.channels ) + dev->maxOutputChannels = hwfmt.play.channels; + dev->defaultSampleRate = (dev->maxOutputChannels > 0) ? + hwfmt.play.sample_rate : hwfmt.record.sample_rate; + } +#endif + +#ifdef AUDIO_GETPROPS + if( ioctl(fd, AUDIO_GETPROPS, &props) != -1 ) + { + if( (props & AUDIO_PROP_PLAYBACK) == 0 ) + dev->maxOutputChannels = 0; + if( (props & AUDIO_PROP_CAPTURE) == 0 ) + dev->maxInputChannels = 0; + } +#endif + +#ifndef __sun + AUDIO_INITINFO(&info); + if( dev->maxOutputChannels > 0 ) + { + info.play.encoding = AUDIO_ENCODING_SLINEAR; + info.play.precision = 16; + info.play.sample_rate = dev->defaultSampleRate; + info.play.channels = dev->maxOutputChannels; + } + if( dev->maxInputChannels > 0 ) + { + info.record.encoding = AUDIO_ENCODING_SLINEAR; + info.record.precision = 16; + info.record.sample_rate = dev->defaultSampleRate; + info.record.channels = dev->maxInputChannels; + } + if( ioctl(fd, AUDIO_SETINFO, &info) != -1 && + ioctl(fd, AUDIO_GETBUFINFO, &info) != -1 ) + { + if( dev->maxOutputChannels > 0 ) + { + dev->defaultLowOutputLatency = + dev->defaultHighOutputLatency = + info.blocksize / (info.play.channels * (info.play.precision / 8)) / + (double)info.play.sample_rate; + } + if( dev->maxInputChannels > 0 ) + { + dev->defaultLowInputLatency = + dev->defaultHighInputLatency = + info.blocksize / (info.record.channels * (info.record.precision / 8)) / + (double)info.record.sample_rate; + } + } +#endif + + if( common->info.defaultInputDevice == paNoDevice && dev->maxInputChannels > 0 ) + common->info.defaultInputDevice = deviceCount; + + if( common->info.defaultOutputDevice == paNoDevice && dev->maxOutputChannels > 0 ) + common->info.defaultOutputDevice = deviceCount; + + common->deviceInfos[deviceCount++] = dev; + + close(fd); + fd = -1; + } + + common->info.deviceCount = deviceCount; + + *hostApi = common; + + PaUtil_InitializeStreamInterface( &audioIOHostApi->callbackStreamInterface, CloseStream, StartStream, + StopStream, AbortStream, IsStreamStopped, IsStreamActive, + GetStreamTime, GetStreamCpuLoad, + PaUtil_DummyRead, PaUtil_DummyWrite, + PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable ); + + PaUtil_InitializeStreamInterface( &audioIOHostApi->blockingStreamInterface, CloseStream, StartStream, + StopStream, AbortStream, IsStreamStopped, IsStreamActive, + GetStreamTime, PaUtil_DummyGetCpuLoad, + ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable ); + return result; + +error: + if( fd != -1 ) + close(fd); + + if( audioIOHostApi ) + { + if( audioIOHostApi->allocations ) + { + PaUtil_FreeAllAllocations( audioIOHostApi->allocations ); + PaUtil_DestroyAllocationGroup( audioIOHostApi->allocations ); + } + free( audioIOHostApi ); + } + return result; +} + + +static void Terminate( struct PaUtilHostApiRepresentation *hostApi ) +{ + PaAudioIOHostApiRepresentation *audioIOHostApi = (PaAudioIOHostApiRepresentation*)hostApi; + + if( audioIOHostApi ) + { + if( audioIOHostApi->allocations ) + { + PaUtil_FreeAllAllocations( audioIOHostApi->allocations ); + PaUtil_DestroyAllocationGroup( audioIOHostApi->allocations ); + } + free( audioIOHostApi ); + } +} + + +static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, + const PaStreamParameters *inputParameters, + const PaStreamParameters *outputParameters, + double sampleRate ) +{ + int inputChannelCount, outputChannelCount; + PaSampleFormat inputSampleFormat, outputSampleFormat; + PaError result = paFormatIsSupported; + PaDeviceInfo *indev, *outdev; + struct audio_info info; + int fd = -1; + + if( inputParameters ) + { + inputChannelCount = inputParameters->channelCount; + inputSampleFormat = inputParameters->sampleFormat; + + /* all standard sample formats are supported by the buffer adapter, + this implementation doesn't support any custom sample formats */ + if( inputSampleFormat & paCustomFormat ) + return paSampleFormatNotSupported; + + /* unless alternate device specification is supported, reject the use of + paUseHostApiSpecificDeviceSpecification */ + + if( inputParameters->device == paUseHostApiSpecificDeviceSpecification ) + return paInvalidDevice; + + indev = hostApi->deviceInfos[ inputParameters->device ]; + + /* check that input device can support inputChannelCount */ + if( inputChannelCount > indev->maxInputChannels ) + return paInvalidChannelCount; + + /* validate inputStreamInfo */ + if( inputParameters->hostApiSpecificStreamInfo ) + return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ + } + else + { + inputChannelCount = 0; + } + + if( outputParameters ) + { + outputChannelCount = outputParameters->channelCount; + outputSampleFormat = outputParameters->sampleFormat; + + /* all standard sample formats are supported by the buffer adapter, + this implementation doesn't support any custom sample formats */ + if( outputSampleFormat & paCustomFormat ) + return paSampleFormatNotSupported; + + /* unless alternate device specification is supported, reject the use of + paUseHostApiSpecificDeviceSpecification */ + + if( outputParameters->device == paUseHostApiSpecificDeviceSpecification ) + return paInvalidDevice; + + outdev = hostApi->deviceInfos[ outputParameters->device ]; + + /* check that output device can support outputChannelCount */ + if( outputChannelCount > outdev->maxOutputChannels ) + return paInvalidChannelCount; + + /* validate outputStreamInfo */ + if( outputParameters->hostApiSpecificStreamInfo ) + return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ + } + else + { + outputChannelCount = 0; + } + + if( inputChannelCount > 0 && outputChannelCount > 0 ) + { + if( strcmp(indev->name, outdev->name) == 0 ) + { + PA_UNLESS( (fd = open(indev->name, O_RDWR | O_NONBLOCK)) != -1, paDeviceUnavailable ); + AUDIO_INITINFO(&info); + info.play.channels = outputChannelCount; + info.record.channels = inputChannelCount; + PA_UNLESS( ioctl(fd, AUDIO_SETINFO, &info) != -1, paInvalidChannelCount ); + AUDIO_INITINFO(&info); + info.play.sample_rate = sampleRate; + info.record.sample_rate = sampleRate; + PA_UNLESS( ioctl(fd, AUDIO_SETINFO, &info) != -1, paInvalidSampleRate ); + close(fd); + return result; + } + } + + if( inputChannelCount > 0 ) + { + PA_UNLESS( (fd = open(indev->name, O_RDONLY | O_NONBLOCK)) != -1, paDeviceUnavailable ); + AUDIO_INITINFO(&info); + info.record.channels = inputChannelCount; + PA_UNLESS( ioctl(fd, AUDIO_SETINFO, &info) != -1, paInvalidChannelCount ); + AUDIO_INITINFO(&info); + info.record.sample_rate = sampleRate; + PA_UNLESS( ioctl(fd, AUDIO_SETINFO, &info) != -1, paInvalidSampleRate ); + close(fd); + fd = -1; + } + + if( outputChannelCount > 0 ) + { + PA_UNLESS( (fd = open(outdev->name, O_WRONLY | O_NONBLOCK)) != -1, paDeviceUnavailable ); + AUDIO_INITINFO(&info); + info.play.channels = outputChannelCount; + PA_UNLESS( ioctl(fd, AUDIO_SETINFO, &info) != -1, paInvalidChannelCount ); + AUDIO_INITINFO(&info); + info.play.sample_rate = sampleRate; + PA_UNLESS( ioctl(fd, AUDIO_SETINFO, &info) != -1, paInvalidSampleRate ); + close(fd); + fd = -1; + } + +error: + if( result == paInvalidChannelCount ) + PA_DEBUG(("PaAudioIO %s: Invalid channels %d in %d out\n", __FUNCTION__, inputChannelCount, outputChannelCount)); + if( result == paInvalidSampleRate ) + PA_DEBUG(("PaAudioIO %s: Invalid sample rate %d Hz\n", __FUNCTION__, (int)sampleRate)); + if( fd != -1 ) + close(fd); + return result; +} + +typedef struct PaAudioIOComponent +{ + int fd; + char name[16]; + void *chanbufs[16]; + void *buffer; + unsigned int bufferSize; /* in frames */ + unsigned int channels; + unsigned int frameSize; /* precision in bytes * channel count */ +} +PaAudioIOComponent; + +typedef struct PaAudioIOStream +{ + PaUtilStreamRepresentation streamRepresentation; + PaUtilCpuLoadMeasurer cpuLoadMeasurer; + PaUtilBufferProcessor bufferProcessor; + PaUtilThreading threading; + PaAudioIOComponent play, record; + bool active, stopped; + bool neverDropInput; + uint64_t framesProcessed; + uint64_t eof; + double sampleRate; +} +PaAudioIOStream; + +/* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */ + +static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, + PaStream** s, + const PaStreamParameters *inputParameters, + const PaStreamParameters *outputParameters, + double sampleRate, + unsigned long framesPerBuffer, + PaStreamFlags streamFlags, + PaStreamCallback *streamCallback, + void *userData ) +{ + PaError result = paNoError; + PaAudioIOHostApiRepresentation *audioIOHostApi = (PaAudioIOHostApiRepresentation*)hostApi; + PaAudioIOStream *stream = 0; + unsigned long framesPerHostBuffer = framesPerBuffer; /* these may not be equivalent for all implementations */ + int inputChannelCount, outputChannelCount; + PaSampleFormat inputSampleFormat, outputSampleFormat; + PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat; + PaTime inputLatency = .04, outputLatency = .04; + PaDeviceInfo *indev, *outdev; + struct audio_info info; + + /* validate platform specific flags */ + if( (streamFlags & paPlatformSpecificFlags) != 0 ) + return paInvalidFlag; /* unexpected platform specific flag */ + + if( inputParameters ) + { + inputChannelCount = inputParameters->channelCount; + inputSampleFormat = inputParameters->sampleFormat; + + /* unless alternate device specification is supported, reject the use of + paUseHostApiSpecificDeviceSpecification */ + + if( inputParameters->device == paUseHostApiSpecificDeviceSpecification ) + return paInvalidDevice; + + indev = hostApi->deviceInfos[ inputParameters->device ]; + + /* check that input device can support inputChannelCount */ + if( inputChannelCount > indev->maxInputChannels ) + return paInvalidChannelCount; + + /* validate inputStreamInfo */ + if( inputParameters->hostApiSpecificStreamInfo ) + return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ + } + else + { + inputChannelCount = 0; + inputSampleFormat = hostInputSampleFormat = paInt16; /* Surpress 'uninitialised var' warnings. */ + } + + if( outputParameters ) + { + outputChannelCount = outputParameters->channelCount; + outputSampleFormat = outputParameters->sampleFormat; + + /* unless alternate device specification is supported, reject the use of + paUseHostApiSpecificDeviceSpecification */ + + if( outputParameters->device == paUseHostApiSpecificDeviceSpecification ) + return paInvalidDevice; + + outdev = hostApi->deviceInfos[ outputParameters->device ]; + + /* check that output device can support outputChannelCount */ + if( outputChannelCount > outdev->maxOutputChannels ) + return paInvalidChannelCount; + + /* validate outputStreamInfo */ + if( outputParameters->hostApiSpecificStreamInfo ) + return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ + } + else + { + outputChannelCount = 0; + outputSampleFormat = hostOutputSampleFormat = paInt16; /* Surpress 'uninitialized var' warnings. */ + } + + PA_UNLESS(stream = calloc( 1, sizeof(PaAudioIOStream) ), paInsufficientMemory); + + stream->play.fd = stream->record.fd = -1; + stream->stopped = true; + stream->neverDropInput = streamFlags & paNeverDropInput; + + if( inputChannelCount > 0 && outputChannelCount > 0) + { + if( inputParameters->device == outputParameters->device ) + { + PA_DEBUG(("PaAudioIO %s: Opening device %s in full duplex\n", __FUNCTION__, indev->name)); + PA_UNLESS( (stream->play.fd = open(indev->name, O_RDWR)) != -1, paDeviceUnavailable ); + stream->record.fd = stream->play.fd; + } + } + + if( inputChannelCount > 0 ) + { + if( stream->record.fd == -1 ) + PA_UNLESS((stream->record.fd = open(indev->name, O_RDONLY)) != -1, paDeviceUnavailable); + + memcpy(stream->record.name, indev->name, strlen(indev->name)); + + hostInputSampleFormat = + PaUtil_SelectClosestAvailableFormat( GetSupportedEncodings(stream->record.fd, true), inputSampleFormat ); + + AUDIO_INITINFO(&info); + if( PaFormatToAudioIOFormat(hostInputSampleFormat, &info.record ) != paNoError || + ioctl(stream->record.fd, AUDIO_SETINFO, &info) < 0 ) + { + result = paSampleFormatNotSupported; + goto error; + } + + AUDIO_INITINFO(&info); + info.record.sample_rate = sampleRate; + PA_UNLESS( ioctl(stream->record.fd, AUDIO_SETINFO, &info) != -1, paInvalidSampleRate ); + + AUDIO_INITINFO(&info); + info.record.channels = inputChannelCount; + PA_UNLESS( ioctl(stream->record.fd, AUDIO_SETINFO, &info) != -1, paInvalidChannelCount ); + + PA_UNLESS( ioctl(stream->record.fd, AUDIO_GETINFO, &info) != -1, paDeviceUnavailable ); + + PA_DEBUG(("PaAudioIO %s: %u-bit %u-channel recording stream at %u Hz\n", __FUNCTION__, + info.record.precision, info.record.channels, info.record.sample_rate)); + + sampleRate = info.record.sample_rate; + + stream->record.channels = inputChannelCount = info.record.channels; + stream->record.frameSize = (info.record.precision / 8) * info.record.channels; + stream->record.bufferSize = framesPerBuffer; + +#ifndef __sun + inputLatency = (info.blocksize / stream->record.frameSize) + + PaUtil_GetBufferProcessorInputLatencyFrames( &stream->bufferProcessor ) / sampleRate; +#else + inputLatency += PaUtil_GetBufferProcessorInputLatencyFrames( &stream->bufferProcessor ) / sampleRate; +#endif + + if( framesPerBuffer == paFramesPerBufferUnspecified ) + { +#ifndef __sun + stream->record.bufferSize = info.blocksize / stream->record.frameSize; +#else + stream->record.bufferSize = AUDIOIO_DEFAULT_FRAMES; +#endif + framesPerBuffer = framesPerHostBuffer = stream->record.bufferSize; + } + + PA_UNLESS(stream->record.buffer = calloc(stream->record.bufferSize, stream->record.frameSize), paInsufficientMemory); + } + + if( outputChannelCount > 0 ) + { + if( stream->play.fd == -1 ) + PA_UNLESS((stream->play.fd = open(outdev->name, O_WRONLY)) != -1, paDeviceUnavailable); + + memcpy(stream->play.name, outdev->name, strlen(outdev->name)); + + hostOutputSampleFormat = + PaUtil_SelectClosestAvailableFormat( GetSupportedEncodings(stream->play.fd, false), outputSampleFormat ); + + AUDIO_INITINFO(&info); + if( PaFormatToAudioIOFormat(hostOutputSampleFormat, &info.play ) != paNoError || + ioctl(stream->play.fd, AUDIO_SETINFO, &info) < 0 ) + { + result = paSampleFormatNotSupported; + goto error; + } + + AUDIO_INITINFO(&info); + info.play.sample_rate = sampleRate; + PA_UNLESS( ioctl(stream->play.fd, AUDIO_SETINFO, &info) != -1, paInvalidSampleRate ); + + AUDIO_INITINFO(&info); + info.play.channels = outputChannelCount; + PA_UNLESS( ioctl(stream->play.fd, AUDIO_SETINFO, &info) != -1, paInvalidChannelCount ); + + PA_UNLESS( ioctl(stream->play.fd, AUDIO_GETINFO, &info) != -1, paDeviceUnavailable ); + + PA_DEBUG(("PaAudioIO %s: %u-bit %u-channel playback stream at %u Hz\n", __FUNCTION__, + info.play.precision, info.play.channels, info.play.sample_rate)); + + sampleRate = info.play.sample_rate; + + stream->play.channels = outputChannelCount = info.play.channels; + stream->play.frameSize = (info.play.precision / 8) * info.play.channels; + stream->play.bufferSize = framesPerBuffer; + +#ifndef __sun + outputLatency = (info.blocksize / stream->play.frameSize) + + PaUtil_GetBufferProcessorOutputLatencyFrames( &stream->bufferProcessor ) / sampleRate; +#else + outputLatency += PaUtil_GetBufferProcessorInputLatencyFrames( &stream->bufferProcessor ) / sampleRate; +#endif + + if( framesPerBuffer == paFramesPerBufferUnspecified ) + { +#ifndef __sun + stream->play.bufferSize = info.blocksize / stream->play.frameSize; +#else + stream->play.bufferSize = AUDIOIO_DEFAULT_FRAMES; +#endif + framesPerBuffer = framesPerHostBuffer = stream->play.bufferSize; + } + + PA_UNLESS( stream->play.buffer = calloc(stream->play.bufferSize, stream->play.frameSize), paInsufficientMemory ); + } + + stream->sampleRate = sampleRate; + + if( streamCallback ) + { + PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation, + &audioIOHostApi->callbackStreamInterface, streamCallback, userData ); + } + else + { + PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation, + &audioIOHostApi->blockingStreamInterface, streamCallback, userData ); + } + + PA_ENSURE( PaUtil_InitializeThreading( &stream->threading ) ); + + PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate ); + + /* we assume a fixed host buffer size in this example, but the buffer processor + can also support bounded and unknown host buffer sizes by passing + paUtilBoundedHostBufferSize or paUtilUnknownHostBufferSize instead of + paUtilFixedHostBufferSize below. */ + + result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor, + inputChannelCount, inputSampleFormat, hostInputSampleFormat, + outputChannelCount, outputSampleFormat, hostOutputSampleFormat, + sampleRate, streamFlags, framesPerBuffer, + framesPerHostBuffer, paUtilFixedHostBufferSize, + streamCallback, userData ); + if( result != paNoError ) + goto error; + + stream->streamRepresentation.streamInfo.inputLatency = inputLatency; + stream->streamRepresentation.streamInfo.outputLatency = outputLatency; + stream->streamRepresentation.streamInfo.sampleRate = sampleRate; + + *s = (PaStream*)stream; + + return result; + +error: + if( stream != NULL ) + { + if( stream->play.fd != -1) + close( stream->play.fd ); + if( stream->record.fd != -1 && stream->record.fd != stream->play.fd ) + close( stream->record.fd ); + free( stream->play.buffer ); + free( stream->record.buffer ); + free( stream ); + } + return result; +} + +static void *PaAudioIO_AudioThreadProc( void *userData ) +{ + PaError result = paNoError; + PaAudioIOStream *stream = (PaAudioIOStream*)userData; + PaStreamCallbackTimeInfo timeInfo = {0,0,0}; + int callbackResult; + struct audio_info info; + unsigned int pframes, rframes; + size_t off; + + while(!stream->stopped) + { + pframes = rframes = 0; + + if( stream->play.channels > 0 ) + pframes = stream->play.bufferSize; + + if( stream->record.channels > 0 ) + rframes = stream->record.bufferSize; + + if( rframes > 0 ) + { + ssize_t len = rframes * stream->record.frameSize; + PA_ENSURE( (len = read(stream->record.fd, stream->record.buffer, len)) != -1 ); + rframes = len / stream->record.frameSize; + if( pframes > rframes ) + pframes = rframes; + } + + PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer ); + PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo, 0 ); + + if( rframes > 0 ) + { + PaUtil_SetInputFrameCount( &stream->bufferProcessor, rframes ); + PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor, 0, stream->record.buffer, stream->record.channels ); + } + else if ( stream->record.channels > 0 ) + { + PaUtil_SetNoInput( &stream->bufferProcessor ); + } + + if( pframes > 0 ) + { + PaUtil_SetOutputFrameCount( &stream->bufferProcessor, pframes ); + PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor, 0, stream->play.buffer, stream->play.channels ); + } + else if ( stream->play.channels > 0 && stream->neverDropInput ) + { + PaUtil_SetNoOutput( &stream->bufferProcessor ); + } + + callbackResult = paContinue; + pframes = PaUtil_EndBufferProcessing( &stream->bufferProcessor, &callbackResult ); + PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, pframes ); + + stream->framesProcessed += pframes; + + off = 0; + + while( stream->play.channels > 0 && pframes > 0 ) + { + ssize_t len = pframes * stream->play.frameSize; + PA_ENSURE( (len = write(stream->play.fd, stream->play.buffer + off, len)) != -1 ); + pframes -= (len / stream->play.frameSize); + off += len; + } + + if( callbackResult != paContinue ) + break; + } + + if( callbackResult == paAbort ) + { + /* once finished, call the finished callback */ + if( stream->streamRepresentation.streamFinishedCallback != 0 ) + stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData ); + } + else + { + /* once finished, call the finished callback */ + if( stream->streamRepresentation.streamFinishedCallback != 0 ) + stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData ); + } + +error: + PaUtil_ResetCpuLoadMeasurer( &stream->cpuLoadMeasurer ); + stream->active = false; + PA_DEBUG(("PaAudioIO %s: Thread exited\n", __FUNCTION__)); + pthread_exit( NULL ); +} + +/* + When CloseStream() is called, the multi-api layer ensures that + the stream has already been stopped or aborted. +*/ +static PaError CloseStream( PaStream* s ) +{ + PaError result = paNoError; + PaAudioIOStream *stream = (PaAudioIOStream*)s; + + PaUtil_TerminateThreading ( &stream->threading ); + PaUtil_TerminateBufferProcessor( &stream->bufferProcessor ); + PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation ); + + if( stream->play.fd != -1 ) + close(stream->play.fd); + + if( stream->record.fd != -1 && stream->record.fd != stream->play.fd ) + close(stream->record.fd); + + free( stream->play.buffer ); + free( stream->record.buffer ); + free( stream ); + + return result; +} + + +static PaError StartStream( PaStream *s ) +{ + PaError result = paNoError; + PaAudioIOStream *stream = (PaAudioIOStream*)s; + + PaUtil_ResetBufferProcessor( &stream->bufferProcessor ); + + stream->active = true; + stream->stopped = false; + + if( stream->bufferProcessor.streamCallback ) + PA_ENSURE( PaUtil_StartThreading( &stream->threading, &PaAudioIO_AudioThreadProc, stream ) ); + +error: + return result; +} + + +static PaError StopStream( PaStream *s ) +{ + PaError result = paNoError; + PaAudioIOStream *stream = (PaAudioIOStream*)s; + + stream->stopped = true; + + if( stream->bufferProcesso