添加一些关于midi播放的项目

This commit is contained in:
terryLP
2025-03-24 14:30:56 +08:00
parent e31eb22077
commit 498b4ef13b
699 changed files with 186162 additions and 1 deletions
@@ -0,0 +1,371 @@
# Set minimum CMake required version for this project.
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
# Define a C++ project.
project(RtAudio LANGUAGES CXX)
# standards version
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Check for Jack (any OS)
find_library(JACK_LIB jack)
find_package(PkgConfig)
pkg_check_modules(jack jack)
if(JACK_LIB OR jack_FOUND)
set(HAVE_JACK TRUE)
endif()
# Check for Pulse (any OS)
pkg_check_modules(pulse libpulse-simple)
# Check for known non-Linux unix-likes
if (CMAKE_SYSTEM_NAME MATCHES "kNetBSD.*|NetBSD.*")
message(STATUS "NetBSD detected, using OSS")
set(xBSD ON)
elseif(UNIX AND NOT APPLE)
set(LINUX ON)
endif()
# Necessary for Windows
if(MINGW)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif()
# Standard CMake options
option(BUILD_SHARED_LIBS "Build as shared library" ON)
if (NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug;Release;RelWithDebInfo;MinSizeRel")
endif()
if(WIN32)
set(CMAKE_DEBUG_POSTFIX d CACHE STRING "Postfix for debug version of library")
endif()
# Build Options
option(RTAUDIO_BUILD_PYTHON "Build PyRtAudio python bindings" OFF)
set(RTAUDIO_TARGETNAME_UNINSTALL "uninstall" CACHE STRING "Name of 'uninstall' build target")
# API Options
option(RTAUDIO_API_DS "Build DirectSound API" OFF)
option(RTAUDIO_API_ASIO "Build ASIO API" OFF)
option(RTAUDIO_API_WASAPI "Build WASAPI API" ${WIN32})
option(RTAUDIO_API_OSS "Build OSS4 API" ${xBSD})
option(RTAUDIO_API_ALSA "Build ALSA API" ${LINUX})
option(RTAUDIO_API_PULSE "Build PulseAudio API" ${pulse_FOUND})
option(RTAUDIO_API_JACK "Build JACK audio server API" ${HAVE_JACK})
option(RTAUDIO_API_CORE "Build CoreAudio API" ${APPLE})
# Check for functions
include(CheckFunctionExists)
check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
if (HAVE_GETTIMEOFDAY)
add_definitions(-DHAVE_GETTIMEOFDAY)
endif ()
# Add -Wall if possible
if (CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif (CMAKE_COMPILER_IS_GNUCXX)
# Add debug flags
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-D__RTAUDIO_DEBUG__)
if (CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif (CMAKE_COMPILER_IS_GNUCXX)
endif ()
# Read libtool version info from configure.ac
set(R "m4_define\\(\\[lt_([a-z]+)\\], ([0-9]+)\\)")
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" CONFIGAC
REGEX ${R})
foreach(_S ${CONFIGAC})
string(REGEX REPLACE ${R} "\\1" k ${_S})
string(REGEX REPLACE ${R} "\\2" v ${_S})
set(SO_${k} ${v})
endforeach()
math(EXPR SO_current_minus_age "${SO_current} - ${SO_age}")
set(SO_VER "${SO_current_minus_age}")
set(FULL_VER "${SO_current_minus_age}.${SO_age}.${SO_revision}")
# Read package version info from configure.ac
set(R "AC_INIT\\(RtAudio, ([0-9\\.]+),.*\\)")
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" CONFIGAC
REGEX "${R}")
string(REGEX REPLACE "${R}" "\\1" PACKAGE_VERSION "${CONFIGAC}")
# Init variables
set(rtaudio_SOURCES RtAudio.cpp RtAudio.h rtaudio_c.cpp rtaudio_c.h)
set(LINKLIBS)
set(PKGCONFIG_REQUIRES)
set(LIBS_REQUIRES)
set(API_DEFS)
set(API_LIST)
# Tweak API-specific configuration.
# Jack
if (RTAUDIO_API_JACK AND jack_FOUND)
set(NEED_PTHREAD ON)
list(APPEND PKGCONFIG_REQUIRES "jack")
list(APPEND API_DEFS "-D__UNIX_JACK__")
list(APPEND API_LIST "jack")
if(jack_FOUND)
list(APPEND LINKLIBS ${jack_LIBRARIES})
list(APPEND INCDIRS ${jack_INCLUDEDIR})
else()
list(APPEND LINKLIBS ${JACK_LIB})
endif()
endif()
# ALSA
if (RTAUDIO_API_ALSA)
set(NEED_PTHREAD ON)
find_package(ALSA)
if (NOT ALSA_FOUND)
message(FATAL_ERROR "ALSA API requested but no ALSA dev libraries found")
endif()
list(APPEND INCDIRS ${ALSA_INCLUDE_DIR})
list(APPEND LINKLIBS ${ALSA_LIBRARY})
list(APPEND PKGCONFIG_REQUIRES "alsa")
list(APPEND API_DEFS "-D__LINUX_ALSA__")
list(APPEND API_LIST "alsa")
endif()
# OSS
if (RTAUDIO_API_OSS)
set(NEED_PTHREAD ON)
find_library(OSSAUDIO_LIB ossaudio)
if (OSSAUDIO_LIB)
list(APPEND LINKLIBS ossaudio)
# Note: not an error on some systems
endif()
list(APPEND API_DEFS "-D__LINUX_OSS__")
list(APPEND API_LIST "oss")
endif()
# Pulse
if (RTAUDIO_API_PULSE)
set(NEED_PTHREAD ON)
find_library(PULSE_LIB pulse)
find_library(PULSESIMPLE_LIB pulse-simple)
list(APPEND LINKLIBS ${PULSE_LIB} ${PULSESIMPLE_LIB})
list(APPEND PKGCONFIG_REQUIRES "libpulse-simple")
list(APPEND API_DEFS "-D__LINUX_PULSE__")
list(APPEND API_LIST "pulse")
endif()
# CoreAudio
if (RTAUDIO_API_CORE)
find_library(COREAUDIO_LIB CoreAudio)
find_library(COREFOUNDATION_LIB CoreFoundation)
list(APPEND LINKLIBS ${COREAUDIO_LIB} ${COREFOUNDATION_LIB})
list(APPEND LIBS_REQUIRES "-framework CoreAudio -framework CoreFoundation")
list(APPEND API_DEFS "-D__MACOSX_CORE__")
list(APPEND API_LIST "core")
endif()
# ASIO
if (RTAUDIO_API_ASIO)
set(NEED_WIN32LIBS ON)
include_directories(include)
list(APPEND rtaudio_SOURCES
include/asio.cpp
include/asiodrivers.cpp
include/asiolist.cpp
include/iasiothiscallresolver.cpp)
list(APPEND API_DEFS "-D__WINDOWS_ASIO__")
list(APPEND API_LIST "asio")
endif()
# DSound
if (RTAUDIO_API_DS)
set(NEED_WIN32LIBS ON)
list(APPEND LINKLIBS dsound)
list(APPEND API_DEFS "-D__WINDOWS_DS__")
list(APPEND API_LIST "ds")
endif()
# WASAPI
if (RTAUDIO_API_WASAPI)
include_directories(include)
set(NEED_WIN32LIBS ON)
list(APPEND LINKLIBS ksuser mfplat mfuuid wmcodecdspuuid)
list(APPEND API_DEFS "-D__WINDOWS_WASAPI__")
list(APPEND API_LIST "wasapi")
endif()
# Windows libs
if (NEED_WIN32LIBS)
list(APPEND LINKLIBS winmm ole32)
endif()
# pthread
if (NEED_PTHREAD)
find_package(Threads REQUIRED
CMAKE_THREAD_PREFER_PTHREAD
THREADS_PREFER_PTHREAD_FLAG)
list(APPEND LINKLIBS Threads::Threads)
endif()
# Create library targets.
set(LIB_TARGETS)
# Use RTAUDIO_BUILD_SHARED_LIBS / RTAUDIO_BUILD_STATIC_LIBS if they
# are defined, otherwise default to standard BUILD_SHARED_LIBS.
if (DEFINED RTAUDIO_BUILD_SHARED_LIBS)
if (RTAUDIO_BUILD_SHARED_LIBS)
add_library(rtaudio SHARED ${rtaudio_SOURCES})
else()
add_library(rtaudio STATIC ${rtaudio_SOURCES})
set(RTAUDIO_IS_STATIC TRUE)
endif()
elseif (DEFINED RTAUDIO_BUILD_STATIC_LIBS)
if (RTAUDIO_BUILD_STATIC_LIBS)
add_library(rtaudio STATIC ${rtaudio_SOURCES})
set(RTAUDIO_IS_STATIC TRUE)
else()
add_library(rtaudio SHARED ${rtaudio_SOURCES})
endif()
else()
add_library(rtaudio ${rtaudio_SOURCES})
if(NOT BUILD_SHARED_LIBS)
set(RTAUDIO_IS_STATIC TRUE)
endif()
endif()
list(APPEND LIB_TARGETS rtaudio)
# Windows: If RTAUDIO_STATIC_MSVCRT is not set, it defaults to ON when building as a
# static library and OFF when building as a DLL. If you want to have more control, you
# can explicitly override RTAUDIO_STATIC_MSVCRT to turn it off/on. It controls the flags
# related to MSVC runtime linkage in the next clause, below.
if (NOT DEFINED RTAUDIO_STATIC_MSVCRT)
set(RTAUDIO_STATIC_MSVCRT ${RTAUDIO_IS_STATIC})
endif()
# In MSVC, set MD/MT appropriately for a static library
# (From https://github.com/protocolbuffers/protobuf/blob/master/cmake/CMakeLists.txt)
if(MSVC AND RTAUDIO_STATIC_MSVCRT)
foreach(flag_var
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(${flag_var} MATCHES "/MD")
endforeach(flag_var)
endif()
set_target_properties(rtaudio PROPERTIES
SOVERSION ${SO_VER}
VERSION ${FULL_VER})
# Set standard installation directories.
include(GNUInstallDirs)
# Set include paths, populate target interface.
target_include_directories(rtaudio
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE
${INCDIRS}
)
# Set compile-time definitions
target_compile_definitions(rtaudio PRIVATE ${API_DEFS})
target_compile_definitions(rtaudio PRIVATE RTAUDIO_EXPORT)
target_link_libraries(rtaudio ${LINKLIBS})
# Subdirs
include(CTest)
if (NOT DEFINED RTAUDIO_BUILD_TESTING OR RTAUDIO_BUILD_TESTING STREQUAL "")
set(RTAUDIO_BUILD_TESTING ${BUILD_TESTING})
endif()
if (RTAUDIO_BUILD_TESTING)
add_subdirectory(tests)
endif()
# Message
string(REPLACE ";" " " apilist "${API_LIST}")
message(STATUS "Compiling with support for: ${apilist}")
# PkgConfig file
string(REPLACE ";" " " req "${PKGCONFIG_REQUIRES}")
string(REPLACE ";" " " req_libs "${LIBS_REQUIRES}")
string(REPLACE ";" " " api "${API_DEFS}")
set(prefix ${CMAKE_INSTALL_PREFIX})
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/rtaudio.pc.in" "rtaudio.pc" @ONLY)
# Add install rule.
install(TARGETS ${LIB_TARGETS}
EXPORT RtAudioTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rtaudio)
# Install public header files
install(FILES RtAudio.h rtaudio_c.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rtaudio)
# Store the package in the user registry.
export(PACKAGE RtAudio)
# Set installation path for CMake files.
set(RTAUDIO_CMAKE_DESTINATION share/rtaudio)
# Create CMake configuration export file.
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/RtAudioConfig.cmake.in "@PACKAGE_INIT@\n")
if(NEED_PTHREAD)
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/RtAudioConfig.cmake.in "find_package(Threads REQUIRED)\n")
endif()
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/RtAudioConfig.cmake.in "include(\${CMAKE_CURRENT_LIST_DIR}/RtAudioTargets.cmake)")
# Install CMake configuration export file.
include(CMakePackageConfigHelpers)
configure_package_config_file(
${CMAKE_CURRENT_BINARY_DIR}/RtAudioConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/RtAudioConfig.cmake
INSTALL_DESTINATION ${RTAUDIO_CMAKE_DESTINATION}
)
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/RtAudioConfig-version.cmake
VERSION ${FULL_VER}
COMPATIBILITY AnyNewerVersion
)
install(
FILES
${CMAKE_BINARY_DIR}/RtAudioConfig.cmake
${CMAKE_BINARY_DIR}/RtAudioConfig-version.cmake
DESTINATION
${RTAUDIO_CMAKE_DESTINATION}
)
# Export library target (build-tree).
export(EXPORT RtAudioTargets
NAMESPACE RtAudio::)
# Export library target (install-tree).
install(EXPORT RtAudioTargets
DESTINATION ${RTAUDIO_CMAKE_DESTINATION}
NAMESPACE RtAudio::)
# Configure uninstall target.
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/RtAudioConfigUninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/RtAudioConfigUninstall.cmake" @ONLY)
# Create uninstall target.
add_custom_target(${RTAUDIO_TARGETNAME_UNINSTALL}
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/RtAudioConfigUninstall.cmake)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/rtaudio.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
@@ -0,0 +1,10 @@
30.04.2018
* Additions and fixes for realtime operation: (Tim E. Real of MusE)
- Added realtime operation to Pulse driver.
- Fixed ALSA realtime support. Attributes are once again all set
in probeDeviceOpen().
- Fixed OSS realtime support. Same mods as done to ALSA driver.
OSS untested, but should work, it's the same code.
- A diagnostic message (streamed to cerr) in each of the callback
handlers informs the user if realtime is really running.
+27
View File
@@ -0,0 +1,27 @@
RtAudio: a set of realtime audio i/o C++ classes
Copyright (c) 2001-2021 Gary P. Scavone
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.
Any person wishing to distribute modifications to the Software is
asked to send the modifications to the original developer so that
they can be incorporated into the canonical version. This is,
however, not a binding provision of this license.
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.
@@ -0,0 +1,34 @@
SUBDIRS = . tests
if MAKE_DOC
SUBDIRS += doc
endif
AM_CXXFLAGS = @visibility@
lib_LTLIBRARIES = %D%/librtaudio.la
%C%_librtaudio_la_CXXFLAGS = -DRTAUDIO_EXPORT
%C%_librtaudio_la_LDFLAGS = -no-undefined -export-dynamic -version-info @SO_VERSION@
%C%_librtaudio_la_SOURCES = \
%D%/RtAudio.cpp \
%D%/rtaudio_c.cpp
if ASIO
%C%_librtaudio_la_SOURCES += \
include/asio.cpp \
include/asiodrivers.cpp \
include/asiolist.cpp \
include/iasiothiscallresolver.cpp
# due to warning in asiolist.cpp
%C%_librtaudio_la_CXXFLAGS += -Wno-error=unused-but-set-variable
endif
rtaudio_incdir = $(includedir)/rtaudio
rtaudio_inc_HEADERS = \
%D%/RtAudio.h \
%D%/rtaudio_c.h
pkgconfigdatadir = $(libdir)/pkgconfig
pkgconfigdata_DATA = rtaudio.pc
EXTRA_DIST = autogen.sh README.md install.txt contrib include cmake CMakeLists.txt
@@ -0,0 +1,62 @@
# RtAudio
![Build Status](https://github.com/thestk/rtaudio/actions/workflows/ci.yml/badge.svg)
A set of C++ classes that provide a common API for realtime audio input/output across Linux (native ALSA, JACK, PulseAudio and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound, ASIO and WASAPI) operating systems.
By Gary P. Scavone, 2001-2021 (and many other developers!)
This distribution of RtAudio contains the following:
- doc: RtAudio documentation (see doc/html/index.html)
- tests: example RtAudio programs
- include: header and source files necessary for ASIO, DS & OSS compilation
- tests/Windows: Visual C++ .net test program workspace and projects
## Overview
RtAudio is a set of C++ classes that provides a common API (Application Programming Interface) for realtime audio input/output across Linux (native ALSA, JACK, PulseAudio and OSS), Macintosh OS X and Windows (DirectSound, ASIO and WASAPI) operating systems. RtAudio significantly simplifies the process of interacting with computer audio hardware. It was designed with the following objectives:
- object-oriented C++ design
- simple, common API across all supported platforms
- only one source and one header file for easy inclusion in programming projects
- allow simultaneous multi-api support
- support dynamic connection of devices
- provide extensive audio device parameter control
- allow audio device capability probing
- automatic internal conversion for data format, channel number compensation, (de)interleaving, and byte-swapping
RtAudio incorporates the concept of audio streams, which represent audio output (playback) and/or input (recording). Available audio devices and their capabilities can be enumerated and then specified when opening a stream. Where applicable, multiple API support can be compiled and a particular API specified when creating an RtAudio instance. See the \ref apinotes section for information specific to each of the supported audio APIs.
## Building
Several build systems are available. These are:
- autotools (`./autogen.sh; make` from git, or `./configure; make` from tarball release)
- CMake (`mkdir build; cd build; ../cmake; make`)
- meson (`meson build; cd build; ninja`)
See `install.txt` for more instructions about how to select the audio backend API. By
default all detected APIs will be enabled.
We recommend using the autotools-based build for packaging purposes. Please note that
RtAudio is designed as a single `.cpp` and `.h` file so that it is easy to copy directly
into a project. In that case you need to define the appropriate flags for the desired
backend APIs.
## FAQ
### Why does audio only come to one ear when I choose 1-channel output?
RtAudio doesn't automatically turn 1-channel output into stereo output with copied values
to each channel, it really only opens one channel. So, if this is the behaviour you want,
you have to do this copying in your audio stream callback.
## Further Reading
For complete documentation on RtAudio, see the doc directory of the distribution or surf to http://www.music.mcgill.ca/~gary/rtaudio/.
## Legal and ethical:
The RtAudio license is similar to the MIT License. Please see [LICENSE](LICENSE).
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+107
View File
@@ -0,0 +1,107 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
DIE=0
if test -z "$*"; then
echo "**Warning**: I am going to run \`configure' with arguments for"
echo "developer/maintainer mode. If you wish to pass extra arguments,"
echo "(such as --prefix), please specify them on the \`$0'"
echo "command line."
echo "If you wish to run configure yourself, please specify --no-configure."
echo
fi
(test -f $srcdir/configure.ac) || {
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
echo " top-level package directory"
exit 1
}
# Make some directories required by automake, if they don't exist
if ! [ -d config ]; then mkdir -v config; fi
if ! [ -d m4 ]; then mkdir -v m4; fi
if ! autoreconf --version </dev/null >/dev/null 2>&1
then
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`autoconf' installed."
echo "Download the appropriate package for your distribution,"
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
(grep "^LT_INIT" $srcdir/configure.ac >/dev/null) && {
(libtoolize --version) < /dev/null > /dev/null 2>&1 \
&& LIBTOOLIZE=libtoolize || {
(glibtoolize --version) < /dev/null > /dev/null 2>&1 \
&& LIBTOOLIZE=glibtoolize || {
echo
echo "**Error**: You must have \`libtool' installed."
echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
}
}
(automake --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`automake' installed."
echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
DIE=1
NO_AUTOMAKE=yes
}
# if no automake, don't bother testing for aclocal
test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: Missing \`aclocal'. The version of \`automake'"
echo "installed doesn't appear recent enough."
echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
if test "$DIE" -eq 1; then
exit 1
fi
case $CC in
xlc )
am_opt=--include-deps;;
esac
echo "Running aclocal $aclocalinclude ..."
aclocal $ACLOCAL_FLAGS || exit 1
echo "Running $LIBTOOLIZE ..."
$LIBTOOLIZE || exit 1
echo "Running automake --gnu $am_opt ..."
automake --add-missing --gnu $am_opt || exit 1
echo "Running autoconf ..."
autoconf || exit 1
else # autoreconf instead
echo "Running autoreconf --verbose --install ..."
autoreconf --verbose --install || exit 1
fi
if ( echo "$@" | grep -q -e "--no-configure" ); then
NOCONFIGURE=1
fi
conf_flags="--enable-maintainer-mode --enable-debug --disable-silent-rules"
if test x$NOCONFIGURE = x; then
echo Running $srcdir/configure $conf_flags "$@" ...
$srcdir/configure $conf_flags "$@" \
&& echo Now type \`make\' to compile. || exit 1
else
echo Skipping configure process.
fi
@@ -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(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(EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
endif(EXISTS "$ENV{DESTDIR}${file}")
endforeach(file)
@@ -0,0 +1,324 @@
# Process this file with autoconf to produce a configure script.
AC_INIT(RtAudio, 5.2.0, [email protected], rtaudio)
AC_CONFIG_AUX_DIR(config)
AC_CONFIG_SRCDIR(RtAudio.cpp)
AC_CONFIG_FILES([rtaudio.pc Makefile tests/Makefile doc/Makefile doc/Doxyfile])
AM_INIT_AUTOMAKE([1.14 -Wall -Werror foreign subdir-objects])
# libtool version: current:revision:age
#
# If the library source code has changed at all since the last update, then
# increment revision (`c:r:a' becomes `c:r+1:a').
#
# If any interfaces have been added, removed, or changed since the last update,
# increment current, and set revision to 0.
#
# If any interfaces have been added since the last public release, then
# increment age.
#
# If any interfaces have been removed since the last public release, then set
# age to 0.
m4_define([lt_current], 6)
m4_define([lt_revision], 2)
m4_define([lt_age], 0)
m4_define([lt_version_info], [lt_current:lt_revision:lt_age])
m4_define([lt_current_minus_age], [m4_eval(lt_current - lt_age)])
SO_VERSION=lt_version_info
AC_SUBST(SO_VERSION)
AC_SUBST(api)
AC_SUBST(req)
AC_SUBST(req_libs)
AC_SUBST(visibility)
api=""
req=""
req_libs=""
use_asio=""
# standards version
m4_include([m4/ax_cxx_compile_stdcxx.m4])
AX_CXX_COMPILE_STDCXX(11, noext, mandatory)
# configure flags
AC_ARG_ENABLE(debug, [AS_HELP_STRING([--enable-debug],[enable various debug output])])
AC_ARG_WITH(jack, [AS_HELP_STRING([--with-jack], [choose JACK server support])])
AC_ARG_WITH(alsa, [AS_HELP_STRING([--with-alsa], [choose native ALSA API support (linux only)])])
AC_ARG_WITH(pulse, [AS_HELP_STRING([--with-pulse], [choose PulseAudio API support (unixes)])])
AC_ARG_WITH(oss, [AS_HELP_STRING([--with-oss], [choose OSS API support (unixes)])])
AC_ARG_WITH(core, [AS_HELP_STRING([--with-core], [choose CoreAudio API support (mac only)])])
AC_ARG_WITH(asio, [AS_HELP_STRING([--with-asio], [choose ASIO API support (win32 only)])])
AC_ARG_WITH(dsound, [AS_HELP_STRING([--with-dsound], [choose DirectSound API support (win32 only)])])
AC_ARG_WITH(wasapi, [AS_HELP_STRING([--with-wasapi], [choose Windows Audio Session API support (win32 only)])])
# Check version number coherency between RtAudio.h and configure.ac
AC_MSG_CHECKING([that version numbers are coherent])
RTAUDIO_VERSION=`sed -n 's/#define RTAUDIO_VERSION "\(.*\)"/\1/p' $srcdir/RtAudio.h`
AS_IF([test "x$RTAUDIO_VERSION" != "x$PACKAGE_VERSION"],[
AC_MSG_RESULT([no])
AC_MSG_FAILURE([testing RTAUDIO_VERSION==PACKAGE_VERSION failed, check that RtAudio.h defines RTAUDIO_VERSION as "$PACKAGE_VERSION" or that the first line of configure.ac has been updated.])
],[
AC_MSG_RESULT([yes])
])
# Enable some nice automake features if they are available
m4_ifdef([AM_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
# Fill GXX with something before test.
GXX="no"
# if the user did not provide any CXXFLAGS, we can override them
AS_IF([test "x$CXXFLAGS" = "x" ], [override_cxx=yes], [override_cxx=no])
AS_IF([test "x$CFLAGS" = "x" ], [override_c=yes], [override_c=no])
# Checks for programs.
AC_PROG_CXX(g++ CC c++ cxx)
AM_PROG_AR
AC_PATH_PROG(AR, ar, no)
AS_IF([test "x${AR}" = "xno" ], [
AC_MSG_ERROR([Could not find ar - needed to create a library])
])
# Initialize libtool
LT_INIT([win32-dll])
AC_CONFIG_MACRO_DIR([m4])
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(sys/ioctl.h unistd.h)
# Check compiler and use -Wall if gnu
AS_IF([test "x${GXX}" = "xyes" ], [
CXXFLAGS="-Wall -Wextra ${CXXFLAGS}"
AS_IF([ test "x${enable_debug}" = "xyes" ], [
# Add -Werror in debug mode
CXXFLAGS="-Werror ${CXXFLAGS}"
], [
# hide private symbols in non-debug mode
visibility="-fvisibility=hidden"
])
])
# Check for debug
AC_MSG_CHECKING([whether to compile debug version])
debugflags=""
AS_CASE([${enable_debug}],
[ yes ], [
AC_MSG_RESULT([yes])
AC_DEFINE([__RTAUDIO_DEBUG__])
debugflags="${debugflags} -g -O0"
object_path=Debug
],
[ no ], [
AC_MSG_RESULT([no!])
debugflags="${debugflags} -O3"
], [
AC_MSG_RESULT([no])
])
# For debugging and optimization ... overwrite default because it has both -g and -O2
AS_IF([test "x$debugflags" != x],
AS_IF([test "x$override_cxx" = "xyes" ], CXXFLAGS="$CXXFLAGS $debugflags", CXXFLAGS="$debugflags $CXXFLAGS")
AS_IF([test "x$override_c" = "xyes" ], CFLAGS="$CFLAGS $debugflags", CFLAGS="$debugflags $CFLAGS")
)
# Checks for functions
AC_CHECK_FUNC(gettimeofday, [cppflag="$cppflag -DHAVE_GETTIMEOFDAY"], )
# Checks for doxygen
AC_CHECK_PROG( DOXYGEN, [doxygen], [doxygen] )
AM_CONDITIONAL( MAKE_DOC, [test "x${DOXYGEN}" != x ] )
# Copy doc files to build dir if necessary
AC_CONFIG_LINKS( [doc/release.txt:doc/release.txt] )
AC_CONFIG_LINKS( [doc/doxygen/footer.html:doc/doxygen/footer.html] )
AC_CONFIG_LINKS( [doc/doxygen/error.txt:doc/doxygen/error.txt] )
AC_CONFIG_LINKS( [doc/doxygen/tutorial.txt:doc/doxygen/tutorial.txt] )
AC_CONFIG_LINKS( [doc/doxygen/compiling.txt:doc/doxygen/compiling.txt] )
AC_CONFIG_LINKS( [doc/doxygen/acknowledge.txt:doc/doxygen/acknowledge.txt] )
AC_CONFIG_LINKS( [doc/doxygen/license.txt:doc/doxygen/license.txt] )
AC_CONFIG_LINKS( [doc/doxygen/header.html:doc/doxygen/header.html] )
AC_CONFIG_LINKS( [doc/doxygen/duplex.txt:doc/doxygen/duplex.txt] )
AC_CONFIG_LINKS( [doc/doxygen/settings.txt:doc/doxygen/settings.txt] )
AC_CONFIG_LINKS( [doc/doxygen/probe.txt:doc/doxygen/probe.txt] )
AC_CONFIG_LINKS( [doc/doxygen/playback.txt:doc/doxygen/playback.txt] )
AC_CONFIG_LINKS( [doc/doxygen/multi.txt:doc/doxygen/multi.txt] )
AC_CONFIG_LINKS( [doc/doxygen/recording.txt:doc/doxygen/recording.txt] )
AC_CONFIG_LINKS( [doc/doxygen/apinotes.txt:doc/doxygen/apinotes.txt] )
AC_CONFIG_LINKS( [doc/images/mcgill.gif:doc/images/mcgill.gif] )
AC_CONFIG_LINKS( [doc/images/ccrma.gif:doc/images/ccrma.gif] )
# Checks for package options and external software
AC_CANONICAL_HOST
# Aggregate options into a single string.
AS_IF([test "x$with_jack" = "xyes"], [systems="$systems jack"])
AS_IF([test "x$with_alsa" = "xyes"], [systems="$systems alsa"])
AS_IF([test "x$with_pulse" = "xyes"], [systems="$systems pulse"])
AS_IF([test "x$with_oss" = "xyes"], [systems="$systems oss"])
AS_IF([test "x$with_core" = "xyes"], [systems="$systems core"])
AS_IF([test "x$with_asio" = "xyes"], [systems="$systems asio"])
AS_IF([test "x$with_dsound" = "xyes"], [systems="$systems dsound"])
AS_IF([test "x$with_wasapi" = "xyes"], [systems="$systems wasapi"])
required=" $systems "
# If none, assign defaults if any are known for this OS.
# User must specified with-* options for any unknown OS.
AS_IF([test "x$systems" = "x"],
AS_CASE([$host],
[*-*-netbsd*], [systems="oss"],
[*-*-freebsd*], [systems="oss"],
[*-*-linux*], [systems="alsa pulse jack oss"],
[*-apple*], [systems="core jack"],
[*-mingw32*], [systems="asio dsound wasapi jack"],
[*-mingw64*], [systems="asio dsound wasapi jack"],
[*-msys*], [systems="asio dsound wasapi jack"],
))
# If any were specifically requested disabled, do it.
AS_IF([test "x$with_jack" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v jack`])
AS_IF([test "x$with_alsa" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v alsa`])
AS_IF([test "x$with_pulse" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v pulse`])
AS_IF([test "x$with_oss" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v oss`])
AS_IF([test "x$with_core" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v core`])
AS_IF([test "x$with_asio" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v asio`])
AS_IF([test "x$with_dsound" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v dsound`])
AS_IF([test "x$with_wasapi" = "xno"], [systems=`echo $systems|tr ' ' \\\\n|grep -v wasapi`])
systems=" `echo $systems|tr \\\\n ' '` "
# For each audio system, check if it is selected and found.
# Note: Order specified above is not necessarily respected. However,
# *actual* priority is set at run-time, see RtAudio::openRtApi.
# One AS_CASE per system, since they are not mutually-exclusive.
AS_CASE(["$systems"], [*" alsa "*], [
AC_CHECK_LIB(asound, snd_pcm_open,
[api="$api -D__LINUX_ALSA__"
req="$req alsa"
need_pthread=yes
found="$found ALSA"
LIBS="-lasound $LIBS"],
AS_CASE(["$required"], [*" alsa "*],
AC_MSG_ERROR([ALSA support requires the asound library!])))
])
AS_CASE(["$systems"], [*" pulse "*], [
AC_CHECK_LIB(pulse-simple, pa_simple_flush,
[api="$api -D__LINUX_PULSE__"
req="$req libpulse-simple"
need_pthread=yes
found="$found PulseAudio"
AC_CHECK_LIB(pulse, pa_strerror, [LIBS="$LIBS -lpulse"])
LIBS="-lpulse-simple $LIBS"],
AS_CASE(["$required"], [*" pulse "*],
AC_MSG_ERROR([PulseAudio support requires the pulse-simple library!])))
])
AS_CASE(["$systems"], [*" oss "*], [
# libossaudio not required on some platforms (e.g. linux) so we
# don't break things if it's not found, but issue a warning when we
# are not sure (i.e. not on linux)
AS_CASE([$host], [*-*-linux*], [], [*], [need_ossaudio=yes])
AC_CHECK_LIB(ossaudio, main, [have_ossaudio=true],
AS_CASE(["$required"], [*" oss "*],
AS_IF([test "x$need_ossaudio" = xyes],
AC_MSG_WARN([RtAudio may require the ossaudio library]))))
# linux systems may have soundcard.h but *not* have OSS4 installed,
# we have to actually check if it exports OSS4 symbols
AC_CHECK_DECL(SNDCTL_SYSINFO,
[api="$api -D__LINUX_OSS__"
need_pthread=yes
found="$found OSS"],
AS_CASE(["$required"], [*" oss "*],
AC_MSG_ERROR([sys/soundcard.h not found]))
[],
[#include <sys/soundcard.h>])
])
AS_CASE(["$systems"], [*" jack "*], [
AC_CHECK_LIB(jack, jack_client_open,
[api="$api -D__UNIX_JACK__"
req="$req jack"
need_pthread=yes
found="$found JACK"
LIBS="-ljack $LIBS"],
AS_CASE(["$required"], [*" jack "*],
AC_MSG_ERROR([JACK support requires the jack library!])))
])
AS_CASE(["$systems"], [*" core "*], [
AC_CHECK_HEADER(CoreAudio/CoreAudio.h,
[api="$api -D__MACOSX_CORE__"
req_libs="$req_libs -framework CoreAudio -framework CoreFoundation"
need_pthread=yes
found="$found CoreAudio",
LIBS="$LIBS -framework CoreAudio -framework CoreFoundation"],
AS_CASE(["$required"], [*" core "*],
AC_MSG_ERROR([CoreAudio header files not found!])))
])
AS_CASE(["$systems"], [*" asio "*], [
api="$api -D__WINDOWS_ASIO__"
use_asio=yes
CPPFLAGS="-I$srcdir/include $CPPFLAGS"
need_ole32=yes
found="$found ASIO"
])
AS_CASE(["$systems"], [*" dsound "*], [
AC_CHECK_HEADERS(windows.h)
AC_CHECK_HEADERS(mmsystem.h mmreg.h dsound.h, [], [],
[#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif])
AS_IF([test "x$ac_cv_header_windows_h" = xyes \
&& test "x$ac_cv_header_mmsystem_h" = xyes \
&& test "x$ac_cv_header_mmreg_h" = xyes \
&& test "x$ac_cv_header_dsound_h" = xyes],
[api="$api -D__WINDOWS_DS__"
need_ole32=yes
found="$found DirectSound"
LIBS="-ldsound -lwinmm $LIBS"])
])
AS_CASE(["$systems"], [*" wasapi "*], [
AC_CHECK_HEADERS(windows.h)
AC_CHECK_HEADERS(audioclient.h avrt.h mmdeviceapi.h, [], [],
[#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif])
AS_IF([test "x$ac_cv_header_windows_h" = xyes \
&& test "x$ac_cv_header_audioclient_h" = xyes \
&& test "x$ac_cv_header_avrt_h" = xyes \
&& test "x$ac_cv_header_mmdeviceapi_h" = xyes],
[api="$api -D__WINDOWS_WASAPI__"
CPPFLAGS="-I$srcdir/include $CPPFLAGS"
need_ole32=yes
found="$found WASAPI"
LIBS="-lwinmm -lksuser -lmfplat -lmfuuid -lwmcodecdspuuid $LIBS"])
])
AS_IF([test -n "$need_ole32"], [LIBS="-lole32 $LIBS"])
AS_IF([test -n "$need_pthread"],[
AC_MSG_CHECKING([for pthread])
AC_CHECK_LIB(pthread, pthread_create, ,
AC_MSG_ERROR([RtAudio requires the pthread library!]))])
AC_MSG_CHECKING([for audio API])
# Error case: no known realtime systems found.
AS_IF([test x"$api" = "x"], [
AC_MSG_RESULT([none])
AC_MSG_ERROR([No known system type found for realtime support!])
], [
AC_MSG_RESULT([$found])
])
AM_CONDITIONAL( ASIO, [test "x${use_asio}" = "xyes" ])
CPPFLAGS="$CPPFLAGS $api"
AC_OUTPUT
@@ -0,0 +1,563 @@
package rtaudio
/*
#cgo CXXFLAGS: -g
#cgo LDFLAGS: -lstdc++ -g
#cgo linux CXXFLAGS: -D__LINUX_ALSA__
#cgo linux LDFLAGS: -lm -lasound -pthread
#cgo linux,pulseaudio CXXFLAGS: -D__LINUX_PULSE__
#cgo linux,pulseaudio LDFLAGS: -lpulse -lpulse-simple
#cgo jack CXXFLAGS: -D__UNIX_JACK__
#cgo jack LDFLAGS: -ljack
#cgo windows CXXFLAGS: -D__WINDOWS_WASAPI__
#cgo windows LDFLAGS: -lm -lksuser -lmfplat -lmfuuid -lwmcodecdspuuid -lwinmm -lole32 -static
#cgo darwin CXXFLAGS: -D__MACOSX_CORE__
#cgo darwin LDFLAGS: -framework CoreAudio -framework CoreFoundation
#include <stdlib.h>
#include <stdint.h>
#include "rtaudio_stub.h"
extern int goCallback(void *out, void *in, unsigned int nFrames,
double stream_time, rtaudio_stream_status_t status, void *userdata);
static inline void cgoRtAudioOpenStream(rtaudio_t audio,
rtaudio_stream_parameters_t *output_params,
rtaudio_stream_parameters_t *input_params,
rtaudio_format_t format,
unsigned int sample_rate,
unsigned int *buffer_frames,
int cb_id,
rtaudio_stream_options_t *options) {
rtaudio_open_stream(audio, output_params, input_params,
format, sample_rate, buffer_frames,
goCallback, (void *)(uintptr_t)cb_id, options, NULL);
}
*/
import "C"
import (
"errors"
"sync"
"time"
"unsafe"
)
// API is an enumeration of available compiled APIs. Supported API include
// Alsa/PulseAudio/OSS, Jack, CoreAudio, WASAPI/ASIO/DS and dummy API.
type API C.rtaudio_api_t
const (
// APIUnspecified looks for a working compiled API.
APIUnspecified API = C.RTAUDIO_API_UNSPECIFIED
// APILinuxALSA uses the Advanced Linux Sound Architecture API.
APILinuxALSA = C.RTAUDIO_API_LINUX_ALSA
// APILinuxPulse uses the Linux PulseAudio API.
APILinuxPulse = C.RTAUDIO_API_LINUX_PULSE
// APILinuxOSS uses the Linux Open Sound System API.
APILinuxOSS = C.RTAUDIO_API_LINUX_OSS
// APIUnixJack uses the Jack Low-Latency Audio Server API.
APIUnixJack = C.RTAUDIO_API_UNIX_JACK
// APIMacOSXCore uses Macintosh OS-X Core Audio API.
APIMacOSXCore = C.RTAUDIO_API_MACOSX_CORE
// APIWindowsWASAPI uses the Microsoft WASAPI API.
APIWindowsWASAPI = C.RTAUDIO_API_WINDOWS_WASAPI
// APIWindowsASIO uses the Steinberg Audio Stream I/O API.
APIWindowsASIO = C.RTAUDIO_API_WINDOWS_ASIO
// APIWindowsDS uses the Microsoft DirectSound API.
APIWindowsDS = C.RTAUDIO_API_WINDOWS_DS
// APIDummy is a compilable but non-functional API.
APIDummy = C.RTAUDIO_API_DUMMY
)
func (api API) String() string {
switch api {
case APIUnspecified:
return "unspecified"
case APILinuxALSA:
return "alsa"
case APILinuxPulse:
return "pulse"
case APILinuxOSS:
return "oss"
case APIUnixJack:
return "jack"
case APIMacOSXCore:
return "coreaudio"
case APIWindowsWASAPI:
return "wasapi"
case APIWindowsASIO:
return "asio"
case APIWindowsDS:
return "directsound"
case APIDummy:
return "dummy"
}
return "?"
}
// StreamStatus defines over- or underflow flags in the audio callback.
type StreamStatus C.rtaudio_stream_status_t
const (
// StatusInputOverflow indicates that data was discarded because of an
// overflow condition at the driver.
StatusInputOverflow StreamStatus = C.RTAUDIO_STATUS_INPUT_OVERFLOW
// StatusOutputUnderflow indicates that the output buffer ran low, likely
// producing a break in the output sound.
StatusOutputUnderflow StreamStatus = C.RTAUDIO_STATUS_OUTPUT_UNDERFLOW
)
// Version returns current RtAudio library version string.
func Version() string {
return C.GoString(C.rtaudio_version())
}
// CompiledAPI determines the available compiled audio APIs.
func CompiledAPI() (apis []API) {
capis := (*[1 << 27]C.rtaudio_api_t)(unsafe.Pointer(C.rtaudio_compiled_api()))
for i := 0; ; i++ {
api := capis[i]
if api == C.RTAUDIO_API_UNSPECIFIED {
break
}
apis = append(apis, API(api))
}
return apis
}
// DeviceInfo is the public device information structure for returning queried values.
type DeviceInfo struct {
Name string
Probed bool
NumOutputChannels int
NumInputChannels int
NumDuplexChannels int
IsDefaultOutput bool
IsDefaultInput bool
//rtaudio_format_t native_formats;
PreferredSampleRate uint
SampleRates []int
}
// StreamParams is the structure for specifying input or output stream parameters.
type StreamParams struct {
DeviceID uint
NumChannels uint
FirstChannel uint
}
// StreamFlags is a set of RtAudio stream option flags.
type StreamFlags C.rtaudio_stream_flags_t
const (
// FlagsNoninterleaved is set to use non-interleaved buffers (default = interleaved).
FlagsNoninterleaved = C.RTAUDIO_FLAGS_NONINTERLEAVED
// FlagsMinimizeLatency when set attempts to configure stream parameters for lowest possible latency.
FlagsMinimizeLatency = C.RTAUDIO_FLAGS_MINIMIZE_LATENCY
// FlagsHogDevice when set attempts to grab device for exclusive use.
FlagsHogDevice = C.RTAUDIO_FLAGS_HOG_DEVICE
// FlagsScheduleRealtime is set in attempt to select realtime scheduling (round-robin) for the callback thread.
FlagsScheduleRealtime = C.RTAUDIO_FLAGS_SCHEDULE_REALTIME
// FlagsAlsaUseDefault is set to use the "default" PCM device (ALSA only).
FlagsAlsaUseDefault = C.RTAUDIO_FLAGS_ALSA_USE_DEFAULT
)
// StreamOptions is the structure for specifying stream options.
type StreamOptions struct {
Flags StreamFlags
NumBuffers uint
Priotity int
Name string
}
// RtAudio is a "controller" used to select an available audio i/o interface.
type RtAudio interface {
Destroy()
CurrentAPI() API
Devices() ([]DeviceInfo, error)
DefaultOutputDevice() int
DefaultInputDevice() int
Open(out, in *StreamParams, format Format, sampleRate uint, frames uint, cb Callback, opts *StreamOptions) error
Close()
Start() error
Stop() error
Abort() error
IsOpen() bool
IsRunning() bool
Latency() (int, error)
SampleRate() (uint, error)
Time() (time.Duration, error)
SetTime(time.Duration) error
ShowWarnings(bool)
}
type rtaudio struct {
audio C.rtaudio_t
cb Callback
inputChannels int
outputChannels int
format Format
}
var _ RtAudio = &rtaudio{}
// Create a new RtAudio instance using the given API.
func Create(api API) (RtAudio, error) {
audio := C.rtaudio_create(C.rtaudio_api_t(api))
if C.rtaudio_error(audio) != nil {
return nil, errors.New(C.GoString(C.rtaudio_error(audio)))
}
return &rtaudio{audio: audio}, nil
}
func (audio *rtaudio) Destroy() {
C.rtaudio_destroy(audio.audio)
}
func (audio *rtaudio) CurrentAPI() API {
return API(C.rtaudio_current_api(audio.audio))
}
func (audio *rtaudio) DefaultInputDevice() int {
return int(C.rtaudio_get_default_input_device(audio.audio))
}
func (audio *rtaudio) DefaultOutputDevice() int {
return int(C.rtaudio_get_default_output_device(audio.audio))
}
func (audio *rtaudio) Devices() ([]DeviceInfo, error) {
n := C.rtaudio_device_count(audio.audio)
devices := []DeviceInfo{}
for i := C.int(0); i < n; i++ {
cinfo := C.rtaudio_get_device_info(audio.audio, i)
if C.rtaudio_error(audio.audio) != nil {
return nil, errors.New(C.GoString(C.rtaudio_error(audio.audio)))
}
sr := []int{}
for _, r := range cinfo.sample_rates {
if r == 0 {
break
}
sr = append(sr, int(r))
}
devices = append(devices, DeviceInfo{
Name: C.GoString(&cinfo.name[0]),
Probed: cinfo.probed != 0,
NumInputChannels: int(cinfo.input_channels),
NumOutputChannels: int(cinfo.output_channels),
NumDuplexChannels: int(cinfo.duplex_channels),
IsDefaultOutput: cinfo.is_default_output != 0,
IsDefaultInput: cinfo.is_default_input != 0,
PreferredSampleRate: uint(cinfo.preferred_sample_rate),
SampleRates: sr,
})
// TODO: formats
}
return devices, nil
}
// Format defines RtAudio data format type.
type Format int
const (
// FormatInt8 uses 8-bit signed integer.
FormatInt8 Format = C.RTAUDIO_FORMAT_SINT8
// FormatInt16 uses 16-bit signed integer.
FormatInt16 = C.RTAUDIO_FORMAT_SINT16
// FormatInt24 uses 24-bit signed integer.
FormatInt24 = C.RTAUDIO_FORMAT_SINT24
// FormatInt32 uses 32-bit signed integer.
FormatInt32 = C.RTAUDIO_FORMAT_SINT32
// FormatFloat32 uses 32-bit floating point values normalized between (-1..1).
FormatFloat32 = C.RTAUDIO_FORMAT_FLOAT32
// FormatFloat64 uses 64-bit floating point values normalized between (-1..1).
FormatFloat64 = C.RTAUDIO_FORMAT_FLOAT64
)
// Buffer is a common interface for audio buffers of various data format types.
type Buffer interface {
Len() int
Int8() []int8
Int16() []int16
Int24() []Int24
Int32() []int32
Float32() []float32
Float64() []float64
}
// Int24 is a helper type to convert int32 values to int24 and back.
type Int24 [3]byte
// Set Int24 value using the least significant bytes of the given number n.
func (i *Int24) Set(n int32) {
(*i)[0], (*i)[1], (*i)[2] = byte(n&0xff), byte((n&0xff00)>>8), byte((n&0xff0000)>>16)
}
// Get Int24 value as int32.
func (i Int24) Get() int32 {
n := int32(i[0]) | int32(i[1])<<8 | int32(i[2])<<16
if n&0x800000 != 0 {
n |= ^0xffffff
}
return n
}
type buffer struct {
format Format
length int
numChannels int
ptr unsafe.Pointer
}
func (b *buffer) Len() int {
if b.ptr == nil {
return 0
}
return b.length
}
func (b *buffer) Int8() []int8 {
if b.format != FormatInt8 {
return nil
}
if b.ptr == nil {
return nil
}
return (*[1 << 30]int8)(b.ptr)[:b.length*b.numChannels : b.length*b.numChannels]
}
func (b *buffer) Int16() []int16 {
if b.format != FormatInt16 {
return nil
}
if b.ptr == nil {
return nil
}
return (*[1 << 29]int16)(b.ptr)[:b.length*b.numChannels : b.length*b.numChannels]
}
func (b *buffer) Int24() []Int24 {
if b.format != FormatInt24 {
return nil
}
if b.ptr == nil {
return nil
}
return (*[1 << 28]Int24)(b.ptr)[:b.length*b.numChannels : b.length*b.numChannels]
}
func (b *buffer) Int32() []int32 {
if b.format != FormatInt32 {
return nil
}
if b.ptr == nil {
return nil
}
return (*[1 << 27]int32)(b.ptr)[:b.length*b.numChannels : b.length*b.numChannels]
}
func (b *buffer) Float32() []float32 {
if b.format != FormatFloat32 {
return nil
}
if b.ptr == nil {
return nil
}
return (*[1 << 27]float32)(b.ptr)[:b.length*b.numChannels : b.length*b.numChannels]
}
func (b *buffer) Float64() []float64 {
if b.format != FormatFloat64 {
return nil
}
if b.ptr == nil {
return nil
}
return (*[1 << 23]float64)(b.ptr)[:b.length*b.numChannels : b.length*b.numChannels]
}
// Callback is a client-defined function that will be invoked when input data
// is available and/or output data is needed.
type Callback func(out Buffer, in Buffer, dur time.Duration, status StreamStatus) int
var (
mu sync.Mutex
audios = map[int]*rtaudio{}
)
func registerAudio(a *rtaudio) int {
mu.Lock()
defer mu.Unlock()
for i := 0; ; i++ {
if _, ok := audios[i]; !ok {
audios[i] = a
return i
}
}
}
func unregisterAudio(a *rtaudio) {
mu.Lock()
defer mu.Unlock()
for i := 0; i < len(audios); i++ {
if audios[i] == a {
delete(audios, i)
return
}
}
}
func findAudio(k int) *rtaudio {
mu.Lock()
defer mu.Unlock()
return audios[k]
}
//export goCallback
func goCallback(out, in unsafe.Pointer, frames C.uint, sec C.double,
status C.rtaudio_stream_status_t, userdata unsafe.Pointer) C.int {
k := int(uintptr(userdata))
audio := findAudio(k)
dur := time.Duration(time.Microsecond * time.Duration(sec*1000000.0))
inbuf := &buffer{audio.format, int(frames), audio.inputChannels, in}
outbuf := &buffer{audio.format, int(frames), audio.outputChannels, out}
return C.int(audio.cb(outbuf, inbuf, dur, StreamStatus(status)))
}
func (audio *rtaudio) Open(out, in *StreamParams, format Format, sampleRate uint,
frames uint, cb Callback, opts *StreamOptions) error {
var (
cInPtr *C.rtaudio_stream_parameters_t
cOutPtr *C.rtaudio_stream_parameters_t
cOptsPtr *C.rtaudio_stream_options_t
cIn C.rtaudio_stream_parameters_t
cOut C.rtaudio_stream_parameters_t
cOpts C.rtaudio_stream_options_t
)
audio.inputChannels = 0
audio.outputChannels = 0
if out != nil {
audio.outputChannels = int(out.NumChannels)
cOut.device_id = C.uint(out.DeviceID)
cOut.num_channels = C.uint(out.NumChannels)
cOut.first_channel = C.uint(out.FirstChannel)
cOutPtr = &cOut
}
if in != nil {
audio.inputChannels = int(in.NumChannels)
cIn.device_id = C.uint(in.DeviceID)
cIn.num_channels = C.uint(in.NumChannels)
cIn.first_channel = C.uint(in.FirstChannel)
cInPtr = &cIn
}
if opts != nil {
cOpts.flags = C.rtaudio_stream_flags_t(opts.Flags)
cOpts.num_buffers = C.uint(opts.NumBuffers)
cOpts.priority = C.int(opts.Priotity)
cOptsPtr = &cOpts
}
framesCount := C.uint(frames)
audio.format = format
audio.cb = cb
k := registerAudio(audio)
C.cgoRtAudioOpenStream(audio.audio, cOutPtr, cInPtr,
C.rtaudio_format_t(format), C.uint(sampleRate), &framesCount, C.int(k), cOptsPtr)
if C.rtaudio_error(audio.audio) != nil {
return errors.New(C.GoString(C.rtaudio_error(audio.audio)))
}
return nil
}
func (audio *rtaudio) Close() {
unregisterAudio(audio)
C.rtaudio_close_stream(audio.audio)
}
func (audio *rtaudio) Start() error {
C.rtaudio_start_stream(audio.audio)
if C.rtaudio_error(audio.audio) != nil {
return errors.New(C.GoString(C.rtaudio_error(audio.audio)))
}
return nil
}
func (audio *rtaudio) Stop() error {
C.rtaudio_stop_stream(audio.audio)
if C.rtaudio_error(audio.audio) != nil {
return errors.New(C.GoString(C.rtaudio_error(audio.audio)))
}
return nil
}
func (audio *rtaudio) Abort() error {
C.rtaudio_abort_stream(audio.audio)
if C.rtaudio_error(audio.audio) != nil {
return errors.New(C.GoString(C.rtaudio_error(audio.audio)))
}
return nil
}
func (audio *rtaudio) IsOpen() bool {
return C.rtaudio_is_stream_open(audio.audio) != 0
}
func (audio *rtaudio) IsRunning() bool {
return C.rtaudio_is_stream_running(audio.audio) != 0
}
func (audio *rtaudio) Latency() (int, error) {
latency := C.rtaudio_get_stream_latency(audio.audio)
if C.rtaudio_error(audio.audio) != nil {
return 0, errors.New(C.GoString(C.rtaudio_error(audio.audio)))
}
return int(latency), nil
}
func (audio *rtaudio) SampleRate() (uint, error) {
sampleRate := C.rtaudio_get_stream_sample_rate(audio.audio)
if C.rtaudio_error(audio.audio) != nil {
return 0, errors.New(C.GoString(C.rtaudio_error(audio.audio)))
}
return uint(sampleRate), nil
}
func (audio *rtaudio) Time() (time.Duration, error) {
sec := C.rtaudio_get_stream_time(audio.audio)
if C.rtaudio_error(audio.audio) != nil {
return 0, errors.New(C.GoString(C.rtaudio_error(audio.audio)))
}
return time.Duration(time.Microsecond * time.Duration(sec*1000000.0)), nil
}
func (audio *rtaudio) SetTime(t time.Duration) error {
sec := float64(t) * 1000000.0 / float64(time.Microsecond)
C.rtaudio_set_stream_time(audio.audio, C.double(sec))
if C.rtaudio_error(audio.audio) != nil {
return errors.New(C.GoString(C.rtaudio_error(audio.audio)))
}
return nil
}
func (audio *rtaudio) ShowWarnings(show bool) {
if show {
C.rtaudio_show_warnings(audio.audio, 1)
} else {
C.rtaudio_show_warnings(audio.audio, 0)
}
}
@@ -0,0 +1,4 @@
#include "../../../RtAudio.h"
#include "../../../RtAudio.cpp"
#include "../../../rtaudio_c.cpp"
@@ -0,0 +1 @@
#include "../../../rtaudio_c.h"
@@ -0,0 +1,71 @@
package rtaudio
import (
"log"
"math"
"time"
)
func ExampleCompiledAPI() {
log.Println("RtAudio version: ", Version())
for _, api := range CompiledAPI() {
log.Println("Compiled API: ", api)
}
}
func ExampleRtAudio_Devices() {
audio, err := Create(APIUnspecified)
if err != nil {
log.Fatal(err)
}
defer audio.Destroy()
devices, err := audio.Devices()
if err != nil {
log.Fatal(err)
}
for _, d := range devices {
log.Printf("Audio device: %#v\n", d)
}
}
func ExampleRtAudio_Open() {
const (
sampleRate = 44100
bufSz = 512
freq = 440.0
)
phase := 0.0
audio, err := Create(APIUnspecified)
if err != nil {
log.Fatal(err)
}
defer audio.Destroy()
params := StreamParams{
DeviceID: uint(audio.DefaultOutputDevice()),
NumChannels: 2,
FirstChannel: 0,
}
options := StreamOptions{
Flags: FlagsAlsaUseDefault,
}
cb := func(out, in Buffer, dur time.Duration, status StreamStatus) int {
samples := out.Float32()
for i := 0; i < len(samples)/2; i++ {
sample := float32(math.Sin(2 * math.Pi * phase))
phase += freq / sampleRate
samples[i*2] = sample
samples[i*2+1] = sample
}
return 0
}
err = audio.Open(&params, nil, FormatFloat32, sampleRate, bufSz, cb, &options)
if err != nil {
log.Fatal(err)
}
defer audio.Close()
audio.Start()
defer audio.Stop()
time.Sleep(3 * time.Second)
}
@@ -0,0 +1,106 @@
from __future__ import print_function
import threading
import rtaudio as rt
from math import cos
import struct
class audio_generator:
def __init__(self):
self.idx = -1
self.freq = 440.
def __call__(self):
self.idx += 1
if self.idx%48000 == 0:
self.freq *= 2**(1/12.)
return 0.5*cos(2.*3.1416*self.freq*self.idx/48000.)
class callback:
def __init__(self, gen):
self.gen = gen
self.i = 0
def __call__(self,playback, capture):
[struct.pack_into("f", playback, 4*o, self.gen()) for o in range(256)]
self.i = self.i + 256
if self.i > 48000*10:
print('.')
return 1
try:
# if we have numpy, replace the above class
import numpy as np
class callback:
def __init__(self, gen):
print('Using Numpy.')
self.freq = 440.
t = np.arange(256, dtype=np.float32) / 48000.0
self.phase = 2*np.pi*t
self.inc = 2*np.pi*256/48000
self.k = 0
def __call__(self, playback, capture):
# Calculate sinusoid using numpy vector operation, as
# opposed to per-sample computations in the generator
# above that must be collected and packed one at a time.
self.k += 256
if self.k > 48000:
self.freq *= 2**(1/12.)
self.k = 0
self.phase += self.inc
samples = 0.5*np.cos(self.phase * self.freq)
# Ensure result is the right size!
assert samples.shape[0] == 256
assert samples.dtype == np.float32
# Use numpy array view to do a once-copy into memoryview
# (ie. we only do a single byte-wise copy of the final
# result into 'playback')
usamples = samples.view(dtype=np.uint8)
playback_array = np.array(playback, copy=False)
np.copyto(playback_array, usamples)
except ModuleNotFoundError:
print('Numpy not available, using struct.')
dac = rt.RtAudio()
n = dac.getDeviceCount()
print('Number of devices available: ', n)
for i in range(n):
try:
print(dac.getDeviceInfo(i))
except rt.RtError as e:
print(e)
print('Default output device: ', dac.getDefaultOutputDevice())
print('Default input device: ', dac.getDefaultInputDevice())
print('is stream open: ', dac.isStreamOpen())
print('is stream running: ', dac.isStreamRunning())
oParams = {'deviceId': 0, 'nChannels': 1, 'firstChannel': 0}
iParams = {'deviceId': 0, 'nChannels': 1, 'firstChannel': 0}
try:
dac.openStream(oParams,oParams,48000,256,callback(audio_generator()) )
except rt.RtError as e:
print(e)
else:
dac.startStream()
import time
print('latency: ', dac.getStreamLatency())
while (dac.isStreamRunning()):
time.sleep(0.1)
print(dac.getStreamTime())
dac.stopStream()
dac.abortStream()
dac.closeStream()
@@ -0,0 +1,57 @@
PyRtAudio - a python wrapper around RtAudio that allows to perform audio i/o operations in real-time from the python language.
By Antoine Lefebvre, 2011
This software is in the development stage. Do not expect compatibility
with future versions. Comments, suggestions, new features, bug fixes,
etc. are welcome.
This distribution of PyRtAudio contains the following:
- rtaudiomodule.cpp: the python wrapper code
- setup.py: a setup script use to compile and install PyRtAudio
- examples: a single PyRtAudioTest.py script
INSTALLATION
The compilation and installation of the PyRtAudio module is handled by
the python Distribution Utilities ("Distutils"). Provided that your
system has a C++ compiler and is properly configure, the following
command should be sufficient:
>> python setup.py install
Please refer to the distutils documentation for installation problems: http://docs.python.org/distutils/index.html
LEGAL AND ETHICAL:
The PyRtAudio license is the same as the RtAudio license:
PyRtAudio: a python wrapper around RtAudio
Copyright (c)2011 Antoine Lefebvre
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.
Any person wishing to distribute modifications to the Software is
asked to send the modifications to the original developer so that
they can be incorporated into the canonical version. This is,
however, not a binding provision of this license.
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.
@@ -0,0 +1,711 @@
/************************************************************************/
/* PyRtAudio: a python wrapper around RtAudio
Copyright (c) 2011 Antoine Lefebvre
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.
Any person wishing to distribute modifications to the Software is
asked to send the modifications to the original developer so that
they can be incorporated into the canonical version. This is,
however, not a binding provision of this license.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/************************************************************************/
// This software is in the development stage
// Do not expect compatibility with future versions.
// Comments, suggestions, new features, bug fixes, etc. are welcome
#include <Python.h>
#include "RtAudio.h"
extern "C" {
typedef struct
{
PyObject_HEAD
#if PY_MAJOR_VERSION < 3
void *padding; // python 2.7 seems to set dac to bad value
// after print_function, causing a crash, no
// idea why, but this fixes it.
#endif
RtAudio *dac;
RtAudioFormat _format;
int _bufferSize;
unsigned int inputChannels;
PyObject *callback_func;
} PyRtAudio;
static PyObject *RtAudioErrorException;
static int callback(void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status, void *data )
{
PyRtAudio* self = (PyRtAudio*) data;
if (status == RTAUDIO_OUTPUT_UNDERFLOW)
printf("underflow.\n");
if (self == NULL) return -1;
float* in = (float *) inputBuffer;
float* out = (float *) outputBuffer;
PyObject *py_callback_func = self->callback_func;
int retval = 0;
if (py_callback_func) {
PyGILState_STATE gstate = PyGILState_Ensure();
#if PY_MAJOR_VERSION >= 3
PyObject* iBuffer = PyMemoryView_FromMemory((char*)in, sizeof(float) * self->inputChannels * nBufferFrames, PyBUF_READ);
PyObject* oBuffer = PyMemoryView_FromMemory((char*)out, sizeof(float) * nBufferFrames, PyBUF_WRITE);
#else
PyObject* iBuffer = PyBuffer_FromMemory(in, sizeof(float) * self->inputChannels * nBufferFrames);
PyObject* oBuffer = PyBuffer_FromReadWriteMemory(out, sizeof(float) * nBufferFrames);
#endif
PyObject *arglist = Py_BuildValue("(O,O)", oBuffer, iBuffer);
if (arglist == NULL) {
printf("error.\n");
PyErr_Print();
PyGILState_Release(gstate);
return 2;
}
// Calling the callback
PyObject *result = PyEval_CallObject(py_callback_func, arglist);
if (PyErr_Occurred() != NULL) {
PyErr_Print();
}
#if PY_MAJOR_VERSION >= 3
else if (result == NULL)
retval = 0;
else if (PyLong_Check(result)) {
retval = PyLong_AsLong(result);
}
#else
else if (PyInt_Check(result)) {
retval = PyInt_AsLong(result);
}
#endif
Py_DECREF(arglist);
Py_DECREF(oBuffer);
Py_DECREF(iBuffer);
Py_XDECREF(result);
PyGILState_Release(gstate);
}
return retval;
}
static void RtAudio_dealloc(PyRtAudio *self)
{
printf("RtAudio_dealloc.\n");
if (self == NULL) return;
if (self->dac) {
self->dac->closeStream();
Py_CLEAR(self->callback_func);
delete self->dac;
}
Py_TYPE(self)->tp_free((PyObject *) self);
}
static PyObject* RtAudio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
printf("RtAudio_new.\n");
PyRtAudio *self;
char *api = NULL;
if(!PyArg_ParseTuple(args, "|s", &api))
return NULL;
self = (PyRtAudio *) type->tp_alloc(type, 0);
if(self == NULL) return NULL;
self->dac = NULL;
self->callback_func = NULL;
try {
if (api == NULL)
self->dac = new RtAudio;
else if(!strcmp(api, "jack"))
self->dac = new RtAudio(RtAudio::UNIX_JACK);
else if(!strcmp(api, "alsa"))
self->dac = new RtAudio(RtAudio::LINUX_ALSA);
else if(!strcmp(api, "oss"))
self->dac = new RtAudio(RtAudio::LINUX_ALSA);
else if(!strcmp(api, "core"))
self->dac = new RtAudio(RtAudio::MACOSX_CORE);
else if(!strcmp(api, "asio"))
self->dac = new RtAudio(RtAudio::WINDOWS_ASIO);
else if(!strcmp(api, "directsound"))
self->dac = new RtAudio(RtAudio::WINDOWS_DS);
}
catch (RtAudioError &error) {
PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
Py_INCREF(RtAudioErrorException);
return NULL;
}
self->dac->showWarnings(false);
//Py_XINCREF(self);
return (PyObject *) self;
}
static int RtAudio_init(PyRtAudio *self, PyObject *args, PyObject *kwds)
{
printf("RtAudio_init.\n");
//if (self == NULL) return 0;
return 0;
}
// This functions does not yet support all the features of the RtAudio::openStream method.
// Please send your patches if you improves this.
static PyObject* RtAudio_openStream(PyRtAudio *self, PyObject *args)
{
if (self == NULL) return NULL;
if (self->dac == NULL) {
printf("the dac is null.\n");
Py_RETURN_NONE;
}
PyObject *oParamsObj;
PyObject *iParamsObj;
int fs;
unsigned int bf;
PyObject *pycallback;
if (!PyArg_ParseTuple(args, "OOiiO", &oParamsObj, &iParamsObj, &fs, &bf, &pycallback))
return NULL;
RtAudio::StreamParameters oParams;
oParams.deviceId = 1;
oParams.nChannels = 1;
oParams.firstChannel = 0;
if (PyDict_Check(oParamsObj)) {
#if PY_MAJOR_VERSION >= 3
if (PyDict_Contains(oParamsObj, PyUnicode_FromString("deviceId"))) {
PyObject *value = PyDict_GetItem(oParamsObj, PyUnicode_FromString("deviceId"));
oParams.deviceId = PyLong_AsLong(value);
}
if (PyDict_Contains(oParamsObj, PyUnicode_FromString("nChannels"))) {
PyObject *value = PyDict_GetItem(oParamsObj, PyUnicode_FromString("nChannels"));
oParams.nChannels = PyLong_AsLong(value);
}
if (PyDict_Contains(oParamsObj, PyUnicode_FromString("firstChannel"))) {
PyObject *value = PyDict_GetItem(oParamsObj, PyUnicode_FromString("firstChannel"));
oParams.firstChannel = PyLong_AsLong(value);
}
#else
if (PyDict_Contains(oParamsObj, PyString_FromString("deviceId"))) {
PyObject *value = PyDict_GetItem(oParamsObj, PyString_FromString("deviceId"));
oParams.deviceId = PyInt_AsLong(value);
}
if (PyDict_Contains(oParamsObj, PyString_FromString("nChannels"))) {
PyObject *value = PyDict_GetItem(oParamsObj, PyString_FromString("nChannels"));
oParams.nChannels = PyInt_AsLong(value);
}
if (PyDict_Contains(oParamsObj, PyString_FromString("firstChannel"))) {
PyObject *value = PyDict_GetItem(oParamsObj, PyString_FromString("firstChannel"));
oParams.firstChannel = PyInt_AsLong(value);
}
#endif
}
else {
printf("First argument must be a dictionary. Default values will be used.\n");
}
RtAudio::StreamParameters iParams;
iParams.deviceId = 1;
iParams.nChannels = 2;
iParams.firstChannel = 0;
if (PyDict_Check(iParamsObj)) {
#if PY_MAJOR_VERSION >= 3
if (PyDict_Contains(iParamsObj, PyUnicode_FromString("deviceId"))) {
PyObject *value = PyDict_GetItem(iParamsObj, PyUnicode_FromString("deviceId"));
iParams.deviceId = PyLong_AsLong(value);
}
if (PyDict_Contains(iParamsObj, PyUnicode_FromString("nChannels"))) {
PyObject *value = PyDict_GetItem(iParamsObj, PyUnicode_FromString("nChannels"));
iParams.nChannels = PyLong_AsLong(value);
}
if (PyDict_Contains(iParamsObj, PyUnicode_FromString("firstChannel"))) {
PyObject *value = PyDict_GetItem(iParamsObj, PyUnicode_FromString("firstChannel"));
iParams.firstChannel = PyLong_AsLong(value);
}
#else
if (PyDict_Contains(iParamsObj, PyString_FromString("deviceId"))) {
PyObject *value = PyDict_GetItem(iParamsObj, PyString_FromString("deviceId"));
iParams.deviceId = PyInt_AsLong(value);
}
if (PyDict_Contains(iParamsObj, PyString_FromString("nChannels"))) {
PyObject *value = PyDict_GetItem(iParamsObj, PyString_FromString("nChannels"));
iParams.nChannels = PyInt_AsLong(value);
}
if (PyDict_Contains(iParamsObj, PyString_FromString("firstChannel"))) {
PyObject *value = PyDict_GetItem(iParamsObj, PyString_FromString("firstChannel"));
iParams.firstChannel = PyInt_AsLong(value);
}
#endif
}
else {
printf("Second argument must be a dictionary. Default values will be used.\n");
}
if (!PyCallable_Check(pycallback)) {
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
Py_XINCREF(PyExc_TypeError);
return NULL;
}
// sanity check the callback ?
Py_INCREF(pycallback); /* Add a reference to new callback */
self->callback_func = pycallback; /*Remember new callback */
// add support for other format
self->_format = RTAUDIO_FLOAT32;
// add support for other options
RtAudio::StreamOptions options;
options.flags = RTAUDIO_NONINTERLEAVED;
try {
if (self->dac->isStreamOpen())
self->dac->closeStream();
self->dac->openStream(&oParams, &iParams, self->_format, fs, &bf, &callback, self, &options);
}
catch ( RtAudioError& error ) {
PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
Py_INCREF(RtAudioErrorException);
return NULL;
}
self->inputChannels = iParams.nChannels;
Py_RETURN_NONE;
}
static PyObject* RtAudio_closeStream(PyRtAudio *self, PyObject *args)
{
printf("RtAudio_closeStream.\n");
if (self == NULL || self->dac == NULL) return NULL;
try {
self->dac->closeStream();
Py_CLEAR(self->callback_func);
}
catch(RtAudioError &error) {
PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
Py_INCREF(RtAudioErrorException);
return NULL;
}
Py_RETURN_NONE;
}
static PyObject* RtAudio_startStream(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
try {
self->dac->startStream();
}
catch(RtAudioError &error) {
PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
Py_INCREF(RtAudioErrorException);
return NULL;
}
Py_RETURN_NONE;
}
static PyObject* RtAudio_stopStream(PyRtAudio *self, PyObject *args)
{
printf("RtAudio_stopStream.\n");
if (self == NULL || self->dac == NULL) return NULL;
try {
self->dac->stopStream();
}
catch(RtAudioError &error) {
PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
Py_INCREF(RtAudioErrorException);
return NULL;
}
Py_RETURN_NONE;
}
static PyObject* RtAudio_abortStream(PyRtAudio *self, PyObject *args)
{
printf("RtAudio_abortStream.\n");
if (self == NULL || self->dac == NULL) return NULL;
try {
self->dac->abortStream();
}
catch(RtAudioError &error) {
PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
Py_INCREF(RtAudioErrorException);
return NULL;
}
Py_RETURN_NONE;
}
static PyObject* RtAudio_isStreamRunning(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
if (self->dac == NULL) {
Py_RETURN_FALSE;
}
if (self->dac->isStreamRunning())
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
static PyObject* RtAudio_isStreamOpen(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
if (self->dac == NULL) {
Py_RETURN_FALSE;
}
if (self->dac->isStreamOpen())
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
static PyObject* RtAudio_getDeviceCount(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong(self->dac->getDeviceCount());
#else
return PyInt_FromLong(self->dac->getDeviceCount());
#endif
}
static PyObject* RtAudio_getDeviceInfo(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
int device;
if (!PyArg_ParseTuple(args, "i", &device))
return NULL;
try {
RtAudio::DeviceInfo info = self->dac->getDeviceInfo(device);
PyObject* info_dict = PyDict_New();
if (info.probed) {
Py_INCREF(Py_True);
PyDict_SetItemString(info_dict, "probed", Py_True);
}
else {
Py_INCREF(Py_False);
PyDict_SetItemString(info_dict, "probed", Py_False);
}
PyObject* obj;
#if PY_MAJOR_VERSION >= 3
obj = PyUnicode_FromString(info.name.c_str());
PyDict_SetItemString(info_dict, "name", obj);
obj = PyLong_FromLong(info.outputChannels);
PyDict_SetItemString(info_dict, "outputChannels", obj);
obj = PyLong_FromLong(info.inputChannels);
PyDict_SetItemString(info_dict, "inputChannels", obj);
obj = PyLong_FromLong(info.duplexChannels);
PyDict_SetItemString(info_dict, "duplexChannels", obj);
#else
obj = PyString_FromString(info.name.c_str());
PyDict_SetItemString(info_dict, "name", obj);
obj = PyInt_FromLong(info.outputChannels);
PyDict_SetItemString(info_dict, "outputChannels", obj);
obj = PyInt_FromLong(info.inputChannels);
PyDict_SetItemString(info_dict, "inputChannels", obj);
obj = PyInt_FromLong(info.duplexChannels);
PyDict_SetItemString(info_dict, "duplexChannels", obj);
#endif
if (info.isDefaultOutput) {
Py_INCREF(Py_True);
PyDict_SetItemString(info_dict, "isDefaultOutput", Py_True);
}
else {
Py_INCREF(Py_False);
PyDict_SetItemString(info_dict, "isDefaultOutput", Py_False);
}
if (info.isDefaultInput) {
Py_INCREF(Py_True);
PyDict_SetItemString(info_dict, "isDefaultInput", Py_True);
}
else {
Py_INCREF(Py_False);
PyDict_SetItemString(info_dict, "isDefaultInput", Py_False);
}
return info_dict;
}
catch(RtAudioError &error) {
PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
Py_INCREF(RtAudioErrorException);
return NULL;
}
}
static PyObject* RtAudio_getDefaultOutputDevice(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong(self->dac->getDefaultOutputDevice());
#else
return PyInt_FromLong(self->dac->getDefaultOutputDevice());
#endif
}
static PyObject* RtAudio_getDefaultInputDevice(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong(self->dac->getDefaultInputDevice());
#else
return PyInt_FromLong(self->dac->getDefaultInputDevice());
#endif
}
static PyObject* RtAudio_getStreamTime(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
return PyFloat_FromDouble( self->dac->getStreamTime() );
}
static PyObject* RtAudio_getStreamLatency(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong( self->dac->getStreamLatency() );
#else
return PyInt_FromLong( self->dac->getStreamLatency() );
#endif
}
static PyObject* RtAudio_getStreamSampleRate(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong( self->dac->getStreamSampleRate() );
#else
return PyInt_FromLong( self->dac->getStreamSampleRate() );
#endif
}
static PyObject* RtAudio_showWarnings(PyRtAudio *self, PyObject *args)
{
if (self == NULL || self->dac == NULL) return NULL;
PyObject *obj;
if (!PyArg_ParseTuple(args, "O", &obj))
return NULL;
if (!PyBool_Check(obj))
return NULL;
if (obj == Py_True)
self->dac->showWarnings(true);
else if (obj == Py_False)
self->dac->showWarnings(false);
else {
printf("not true nor false\n");
}
Py_RETURN_NONE;
}
static PyMethodDef RtAudio_methods[] =
{
// TO BE DONE: getCurrentApi(void)
{"getDeviceCount", (PyCFunction) RtAudio_getDeviceCount, METH_NOARGS,
"A public function that queries for the number of audio devices available."},
{"getDeviceInfo", (PyCFunction) RtAudio_getDeviceInfo, METH_VARARGS,
"Return a dictionary with information for a specified device number."},
{"getDefaultOutputDevice", (PyCFunction) RtAudio_getDefaultOutputDevice, METH_NOARGS,
"A function that returns the index of the default output device."},
{"getDefaultInputDevice", (PyCFunction) RtAudio_getDefaultInputDevice, METH_NOARGS,
"A function that returns the index of the default input device."},
{"openStream", (PyCFunction) RtAudio_openStream, METH_VARARGS,
"A public method for opening a stream with the specified parameters."},
{"closeStream", (PyCFunction) RtAudio_closeStream, METH_NOARGS,
"A function that closes a stream and frees any associated stream memory. "},
{"startStream", (PyCFunction) RtAudio_startStream, METH_NOARGS,
"A function that starts a stream. "},
{"stopStream", (PyCFunction) RtAudio_stopStream, METH_NOARGS,
"Stop a stream, allowing any samples remaining in the output queue to be played. "},
{"abortStream", (PyCFunction) RtAudio_abortStream, METH_NOARGS,
"Stop a stream, discarding any samples remaining in the input/output queue."},
{"isStreamOpen", (PyCFunction) RtAudio_isStreamOpen, METH_NOARGS,
"Returns true if a stream is open and false if not."},
{"isStreamRunning", (PyCFunction) RtAudio_isStreamRunning, METH_NOARGS,
"Returns true if the stream is running and false if it is stopped or not open."},
{"getStreamTime", (PyCFunction) RtAudio_getStreamTime, METH_NOARGS,
"Returns the number of elapsed seconds since the stream was started."},
{"getStreamLatency", (PyCFunction) RtAudio_getStreamLatency, METH_NOARGS,
"Returns the internal stream latency in sample frames."},
{"getStreamSampleRate", (PyCFunction) RtAudio_getStreamSampleRate, METH_NOARGS,
"Returns actual sample rate in use by the stream."},
{"showWarnings", (PyCFunction) RtAudio_showWarnings, METH_VARARGS,
"Specify whether warning messages should be printed to stderr."},
// TO BE DONE: getCompiledApi (std::vector< RtAudio::Api > &apis) throw ()
{NULL}
};
static PyTypeObject RtAudio_type = {
PyVarObject_HEAD_INIT(NULL, 0)
"rtaudio.RtAudio", /*tp_name*/
sizeof(RtAudio), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor) RtAudio_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"Audio input device", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
RtAudio_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)RtAudio_init, /* tp_init */
0, /* tp_alloc */
RtAudio_new, /* tp_new */
0, /* Low-level free-memory routine */
0, /* For PyObject_IS_GC */
0, // PyObject *tp_bases;
0, // PyObject *tp_mro; /* method resolution order */
0, //PyObject *tp_cache;
0, //PyObject *tp_subclasses;
0, //PyObject *tp_weaklist;
0, //destructor tp_del;
//0, /* Type attribute cache version tag. Added in version 2.6 */
};
#if PY_MAJOR_VERSION >= 3
static PyModuleDef RtAudio_module = {
PyModuleDef_HEAD_INIT,
"RtAudio",
"RtAudio wrapper.",
};
#endif
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
#if PY_MAJOR_VERSION >= 3
PyInit_rtaudio(void)
#else
initrtaudio(void)
#endif
{
if (!PyEval_ThreadsInitialized())
PyEval_InitThreads();
if (PyType_Ready(&RtAudio_type) < 0)
#if PY_MAJOR_VERSION >= 3
return NULL;
#else
return;
#endif
#if PY_MAJOR_VERSION >= 3
PyObject* module = PyModule_Create(&RtAudio_module);
if (module == NULL)
return NULL;
#else
PyObject* module = Py_InitModule3("rtaudio", NULL, "RtAudio wrapper.");
if (module == NULL)
return;
#endif
Py_INCREF(&RtAudio_type);
PyModule_AddObject(module, "RtAudio", (PyObject *)&RtAudio_type);
RtAudioErrorException = PyErr_NewException("rtaudio.RtError", NULL, NULL);
Py_INCREF(RtAudioErrorException);
PyModule_AddObject(module, "RtError", RtAudioErrorException);
#if PY_MAJOR_VERSION >= 3
return module;
#else
return;
#endif
}
}
@@ -0,0 +1,56 @@
#!/bin/env python
import os
from distutils.core import setup, Extension
if hasattr(os, 'uname'):
OSNAME = os.uname()[0]
else:
OSNAME = 'Windows'
define_macros = []
libraries = []
extra_link_args = []
extra_compile_args = ['-I../../../']
sources = ['rtaudiomodule.cpp', '../../../RtAudio.cpp']
if OSNAME == 'Linux':
define_macros=[("__LINUX_ALSA__", ''),
('__LINUX_JACK__', '')]
libraries = ['asound', 'jack', 'pthread']
elif OSNAME == 'Darwin':
define_macros = [('__MACOSX_CORE__', '')]
libraries = ['pthread', 'stdc++']
extra_link_args = ['-framework', 'CoreAudio']
elif OSNAME == 'Windows':
define_macros = [('__WINDOWS_DS__', None),
('__WINDOWS_ASIO__', None),
('__LITTLE_ENDIAN__',None),
('WIN32',None)]
libraries = ['winmm', 'dsound', 'Advapi32','Ole32','User32']
sources += ['../../../include/asio.cpp',
'../../../include/asiodrivers.cpp',
'../../../include/asiolist.cpp',
'../../../include/iasiothiscallresolver.cpp']
extra_compile_args.append('-I../../../include/')
extra_compile_args.append('-EHsc')
audio = Extension('rtaudio',
sources=sources,
libraries=libraries,
define_macros=define_macros,
extra_compile_args = extra_compile_args,
extra_link_args = extra_link_args,
)
setup(name = 'rtaudio',
version = '0.1',
description = 'Python RtAudio interface',
ext_modules = [audio])
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,33 @@
MAINTAINERCLEANFILES=Makefile.in
CLEANFILES=doxygen-build.stamp
DOX=Doxyfile
EXTRA_DIST=html
INSTIMAGES=html/doxygen.png
DOC_STAMPS=doxygen-build.stamp
DOC_DIR=$(HTML_DIR)
all-local: doxygen-build.stamp
doxygen-build.stamp: $(DOX) $(top_srcdir)/RtAudio.h
@echo '*** Running doxygen ***'
$(DOXYGEN) $(DOX)
touch doxygen-build.stamp
clean-local:
rm -f *~ *.bak $(DOC_STAMPS) || true
if test -d html; then rm -fr html; fi
if test -d latex; then rm -fr latex; fi
if test -d man; then rm -fr man; fi
distclean-local: clean
rm -f *.stamp || true
if test -d html; then rm -rf html; fi
html-local: $(DOC_STAMPS)
@@ -0,0 +1,48 @@
/*! \page acknowledge Acknowledgements
Many thanks to the following people for providing bug fixes and improvements:
<UL>
<LI>Stephen Sinclair (major code and repository support!)</LI>
<LI>Stefan Arisona</LI>
<LI>bejuryu</LI>
<LI>Vincent B&eacute;nony</LI>
<LI>Francesco Bertolaccini</LI>
<LI>Benjamin Brown</LI>
<LI>Claudio Cabral</LI>
<LI>JP Cimalando</LI>
<LI>Rasmus Ekman</LI>
<LI>Anders Ervik</LI>
<LI>Robin Davies (Windows DS and ASIO)</LI>
<LI>Marcelo Fernandez</LI>
<LI>Taylor Holberton</LI>
<LI>Martin Koegler</LI>
<LI>Dmitry Kostjuchenko</LI>
<LI>Oliver Larkin</LI>
<LI>Jakob Leben</LI>
<LI>Antoine Lefebvre</LI>
<LI>Carlos Luna</LI>
<LI>Connor MacDonald</LI>
<LI>Jasper Mackenzie</LI>
<LI>Dominic Mazzoni</LI>
<LI>Tristan Matthews</LI>
<LI>Peter Meerwald (PulseAudio)</LI>
<LI>Jaromir Mikes</LI>
<LI>rehans</LI>
<LI>Sebastian Reimers</LI>
<LI>Ryan Schmidt</LI>
<LI>Benjamin Schroeder</LI>
<LI>sonoro1234</LI>
<LI>terminator356</LI>
<LI>Marcus Tomlinson (WASAPI)</LI>
<LI>Ryan Williams (Windows non-MS compiler ASIO support)</LI>
<LI>Ed Wildgoose (Linux ALSA and Jack)</LI>
<LI>Serge Zaitsev</LI>
<LI>Iohannes Zm&ouml;lnig</LI>
</UL>
The RtAudio API incorporates many of the concepts developed in the <A href="http://www.portaudio.com/">PortAudio</A> project by Phil Burk and Ross Bencina. Early development also incorporated ideas from Bill Schottstaedt's <A href="http://www-ccrma.stanford.edu/software/snd/sndlib/">sndlib</A>. The CCRMA <A href="http://www-ccrma.stanford.edu/groups/soundwire/">SoundWire group</A> provided valuable feedback during the API proposal stages.
The early 2.0 version of RtAudio was slowly developed over the course of many months while in residence at the <A href="http://www.iua.upf.es/">Institut Universitari de L'Audiovisual (IUA)</A> in Barcelona, Spain and the <A href="http://www.acoustics.hut.fi/">Laboratory of Acoustics and Audio Signal Processing</A> at the Helsinki University of Technology, Finland. Much subsequent development happened while working at the <A href="http://www-ccrma.stanford.edu/">Center for Computer Research in Music and Acoustics (CCRMA)</A> at <A href="http://www.stanford.edu/">Stanford University</A>. All recent versions of RtAudio have been completed while working as an assistant / associate professor of <a href="http://www.music.mcgill.ca/musictech/">Music Technology</a> at <a href="http://www.mcgill.ca/">McGill University</a>. This work was supported in part by the United States Air Force Office of Scientific Research (grant \#F49620-99-1-0293).
*/
@@ -0,0 +1,39 @@
/*! \page apinotes API Notes
RtAudio is designed to provide a common API across the various supported operating systems and audio libraries. Despite that, some issues should be mentioned with regard to each.
\section linux Linux:
RtAudio for Linux was developed under Redhat distributions 7.0 - Fedora. Four different audio APIs are supported on Linux platforms: <A href="http://www.opensound.com/oss.html">OSS</A> (versions >= 4.0), <A href="http://www.alsa-project.org/">ALSA</A>, <A href="http://jackit.sourceforge.net/">Jack</A>, and <A href="http://www.freedesktop.org/wiki/Software/PulseAudio">PulseAudio</A>. Note that RtAudio now only supports the newer version 4.0 OSS API. The ALSA API is now part of the Linux kernel and offers significantly better functionality than the OSS API. RtAudio provides support for the 1.0 and higher versions of ALSA. Jack is a low-latency audio server written primarily for the GNU/Linux operating system. It can connect a number of different applications to an audio device, as well as allow them to share audio between themselves. Input/output latency on the order of 15 milliseconds can typically be achieved using any of the Linux APIs by fine-tuning the RtAudio buffer parameters (without kernel modifications). Latencies on the order of 5 milliseconds or less can be achieved using a low-latency kernel patch and increasing FIFO scheduling priority. The pthread library, which is used for callback functionality, is a standard component of all Linux distributions.
The ALSA library includes OSS emulation support. That means that you can run programs compiled for the OSS API even when using the ALSA drivers and library. It should be noted however that OSS emulation under ALSA is not perfect. Specifically, channel number queries seem to consistently produce invalid results. While OSS emulation is successful for the majority of RtAudio tests, it is recommended that the native ALSA implementation of RtAudio be used on systems which have ALSA drivers installed.
The ALSA implementation of RtAudio makes no use of the ALSA "plug" interface. All necessary data format conversions, channel compensation, de-interleaving, and byte-swapping is handled by internal RtAudio routines.
\section macosx Macintosh OS-X (CoreAudio and Jack):
The Apple CoreAudio API is designed to use a separate callback procedure for each of its audio devices. A single RtAudio duplex stream using two different devices is supported, though it cannot be guaranteed to always behave correctly because we cannot synchronize these two callbacks. The <I>numberOfBuffers</I> parameter to the RtAudio::openStream() function has no affect in this implementation.
It is not possible to have multiple instances of RtAudio accessing the same CoreAudio device.
The RtAudio Jack support can be compiled on Macintosh OS-X systems, as well as in Linux.
\section windowsds Windows (DirectSound):
The \c configure script provides support for the MinGW compiler. DirectSound support is specified with the "--with-ds" flag.
In order to compile RtAudio under Windows for the DirectSound API, you must have the header and source files for DirectSound version 5.0 or higher. As far as I know, there is no DirectSoundCapture support for Windows NT. Audio output latency with DirectSound can be reasonably good, especially since RtAudio version 3.0.2. Input audio latency still tends to be bad but better since version 3.0.2. RtAudio was originally developed with Visual C++ version 6.0 but has been tested with .NET.
The DirectSound version of RtAudio can be compiled with or without the UNICODE preprocessor definition.
\section windowsasio Windows (ASIO):
ASIO support using MinGW and the \c configure script is specified with the "--with-asio" flag.
The Steinberg ASIO audio API allows only a single device driver to be loaded and accessed at a time. ASIO device drivers must be supplied by audio hardware manufacturers, though ASIO emulation is possible on top of systems with DirectSound drivers. The <I>numberOfBuffers</I> parameter to the RtAudio::openStream() function has no affect in this implementation.
A number of ASIO source and header files are required for use with RtAudio. Specifically, an RtAudio project must include the following files: <TT>asio.h,cpp; asiodrivers.h,cpp; asiolist.h,cpp; asiodrvr.h; asiosys.h; ginclude.h; iasiodrv.h; iasiothiscallresolver.h,cpp</TT>. The Visual C++ projects found in <TT>/tests/Windows/</TT> compile both ASIO and DirectSound support.
The Steinberg provided <TT>asiolist</TT> class does not compile when the preprocessor definition UNICODE is defined. Note that this could be an issue when using RtAudio with Qt, though Qt programs appear to compile without the UNICODE definition (try <tt>DEFINES -= UNICODE</tt> in your .pro file). RtAudio with ASIO support has been tested using the MinGW compiler under Windows XP, as well as in the Visual Studio environment.
*/
@@ -0,0 +1,92 @@
/*! \page compiling Debugging & Compiling
\section debug Debugging
If you are having problems getting RtAudio to run on your system, make sure to pass a value of \e true to the RtAudio::showWarnings() function (this is the default setting). A variety of warning messages will be displayed which may help in determining the problem. Also, try using the programs included in the <tt>tests</tt> directory. The program <tt>audioprobe</tt> displays the queried capabilities of all hardware devices found for all APIs compiled. When using the ALSA and JACK APIs, further information can be displayed by defining the preprocessor definition __RTAUDIO_DEBUG__.
\section compile Compiling
In order to compile RtAudio for a specific OS and audio API, it is necessary to supply the appropriate preprocessor definition and library within the compiler statement:
<P>
<TABLE BORDER=2 COLS=5 WIDTH="100%">
<TR BGCOLOR="beige">
<TD WIDTH="5%"><B>OS:</B></TD>
<TD WIDTH="5%"><B>Audio API:</B></TD>
<TD WIDTH="5%"><B>C++ Class:</B></TD>
<TD WIDTH="5%"><B>Preprocessor Definition:</B></TD>
<TD WIDTH="5%"><B>Library or Framework:</B></TD>
<TD><B>Example Compiler Statement:</B></TD>
</TR>
<TR>
<TD>Linux</TD>
<TD>ALSA</TD>
<TD>RtApiAlsa</TD>
<TD>__LINUX_ALSA__</TD>
<TD><TT>asound, pthread</TT></TD>
<TD><TT>g++ -Wall -D__LINUX_ALSA__ -o audioprobe audioprobe.cpp RtAudio.cpp -lasound -lpthread</TT></TD>
</TR>
<TR>
<TD>Linux</TD>
<TD>PulseAudio</TD>
<TD>RtApiPulse</TD>
<TD>__LINUX_PULSE__</TD>
<TD><TT>pthread</TT></TD>
<TD><TT>g++ -Wall -D__LINUX_PULSE__ -o audioprobe audioprobe.cpp RtAudio.cpp -lpthread -lpulse-simple -lpulse</TT></TD>
</TR>
<TR>
<TD>Linux</TD>
<TD>OSS</TD>
<TD>RtApiOss</TD>
<TD>__LINUX_OSS__</TD>
<TD><TT>pthread</TT></TD>
<TD><TT>g++ -Wall -D__LINUX_OSS__ -o audioprobe audioprobe.cpp RtAudio.cpp -lpthread</TT></TD>
</TR>
<TR>
<TD>Linux or Macintosh OS-X</TD>
<TD>Jack Audio Server</TD>
<TD>RtApiJack</TD>
<TD>__UNIX_JACK__</TD>
<TD><TT>jack, pthread</TT></TD>
<TD><TT>g++ -Wall -D__UNIX_JACK__ -o audioprobe audioprobe.cpp RtAudio.cpp $(pkg-config --cflags --libs jack) -lpthread</TT></TD>
</TR>
<TR>
<TD>Macintosh OS-X</TD>
<TD>CoreAudio</TD>
<TD>RtApiCore</TD>
<TD>__MACOSX_CORE__</TD>
<TD><TT>pthread, CoreAudio</TT></TD>
<TD><TT>g++ -Wall -D__MACOSX_CORE__ -o audioprobe audioprobe.cpp RtAudio.cpp -framework CoreAudio -framework CoreFoundation -lpthread</TT></TD>
</TR>
<TR>
<TD>Windows</TD>
<TD>DirectSound</TD>
<TD>RtApiDs</TD>
<TD>__WINDOWS_DS__</TD>
<TD><TT>dsound.lib (ver. 5.0 or higher), multithreaded</TT></TD>
<TD>MinGW: <TT>g++ -Wall -D__WINDOWS_DS__ -o audioprobe audioprobe.cpp RtAudio.cpp -lole32 -lwinmm -ldsound</TT></TD>
</TR>
<TR>
<TD>Windows</TD>
<TD>ASIO</TD>
<TD>RtApiAsio</TD>
<TD>__WINDOWS_ASIO__</TD>
<TD><I>various ASIO header and source files</I></TD>
<TD>MinGW: <TT>g++ -Wall -D__WINDOWS_ASIO__ -Iinclude -o audioprobe audioprobe.cpp RtAudio.cpp asio.cpp asiolist.cpp asiodrivers.cpp iasiothiscallresolver.cpp -lole32</TT></TD>
</TR>
<TR>
<TD>Windows</TD>
<TD>WASAPI</TD>
<TD>RtApiWasapi</TD>
<TD>__WINDOWS_WASAPI__</TD>
<TD>MinGW: <TT>FunctionDiscoveryKeys_devpkey.h, lksuser, lmfplat, lmfuuid, lwmcodecdspuuid, lwinmm, lole32</TT></TD>
<TD>MinGW: <TT>g++ -Wall -D__WINDOWS_WASAPI__ -Iinclude -o audioprobe audioprobe.cpp RtAudio.cpp -lole32 -lwinmm -lksuser -lmfplat -lmfuuid -lwmcodecdspuuid</TT></TD>
</TR>
</TABLE>
<P>
The example compiler statements above could be used to compile the <TT>audioprobe.cpp</TT> example file, assuming that <TT>audioprobe.cpp</TT>, <TT>RtAudio.h</TT>, <TT>RtAudio.cpp</TT> and any other necessary files all exist in the same directory or the include directory.
*/
@@ -0,0 +1,76 @@
/*! \page duplex Duplex Mode
Finally, it is easy to use RtAudio for simultaneous audio input/output, or duplex operation. In this example, we simply pass the input data back to the output.
\code
#include "RtAudio.h"
#include <iostream>
#include <cstdlib>
#include <cstring>
// Pass-through function.
int inout( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status, void *data )
{
// Since the number of input and output channels is equal, we can do
// a simple buffer copy operation here.
if ( status ) std::cout << "Stream over/underflow detected." << std::endl;
unsigned int *bytes = (unsigned int *) data;
memcpy( outputBuffer, inputBuffer, *bytes );
return 0;
}
int main()
{
RtAudio adac;
if ( adac.getDeviceCount() < 1 ) {
std::cout << "\nNo audio devices found!\n";
exit( 0 );
}
// Set the same number of channels for both input and output.
unsigned int bufferBytes, bufferFrames = 512;
RtAudio::StreamParameters iParams, oParams;
iParams.deviceId = 0; // first available device
iParams.nChannels = 2;
oParams.deviceId = 0; // first available device
oParams.nChannels = 2;
try {
adac.openStream( &oParams, &iParams, RTAUDIO_SINT32, 44100, &bufferFrames, &inout, (void *)&bufferBytes );
}
catch ( RtAudioError& e ) {
e.printMessage();
exit( 0 );
}
bufferBytes = bufferFrames * 2 * 4;
try {
adac.startStream();
char input;
std::cout << "\nRunning ... press <enter> to quit.\n";
std::cin.get(input);
// Stop the stream.
adac.stopStream();
}
catch ( RtAudioError& e ) {
e.printMessage();
goto cleanup;
}
cleanup:
if ( adac.isStreamOpen() ) adac.closeStream();
return 0;
}
\endcode
In this example, audio recorded by the stream input will be played out during the next round of audio processing.
Note that a duplex stream can make use of two different devices (except when using the Linux Jack and Windows ASIO APIs). However, this may cause timing problems due to possible device clock variations, unless a common external "sync" is provided.
*/
@@ -0,0 +1,5 @@
/*! \page errors Error Handling
RtAudio makes restrained use of C++ exceptions. That is, exceptions are thrown only when system errors occur that prevent further class operation or when the user makes invalid function calls. In other cases, a warning message may be displayed and an appropriate value is returned. For example, if a system error occurs when processing the RtAudio::getDeviceCount() function, the return value is zero. In such a case, the user cannot expect to make use of most other RtAudio functions because no devices are available (and thus a stream cannot be opened). A client can call the function RtAudio::showWarnings() with a boolean argument to enable or disable the printing of warning messages to <tt>stderr</tt>. By default, warning messages are displayed. There is a protected RtAudio method, error(), that can be modified to globally control how these messages are handled and reported.
*/
@@ -0,0 +1,8 @@
<HR>
<table><tr><td><img src="../images/mcgill.gif" width=165></td>
<td>&copy;2001-2021 Gary P. Scavone, McGill University. All Rights Reserved.<br>Maintained by <a href="http://www.music.mcgill.ca/~gary/">Gary P. Scavone</a>.</td></tr>
</table>
</BODY>
</HTML>
@@ -0,0 +1,10 @@
<HTML>
<HEAD>
<TITLE>The RtAudio Home Page</TITLE>
<LINK HREF="doxygen.css" REL="stylesheet" TYPE="text/css">
<LINK REL="SHORTCUT ICON" HREF="http://www.music.mcgill.ca/~gary/favicon.ico">
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<CENTER>
<a class="qindex" href="index.html">Home</a> &nbsp; <a class="qindex" href="annotated.html">Class/Enum List</a> &nbsp; <a class="qindex" href="files.html">File List</a> &nbsp; <a class="qindex" href="functions.html">Compound Members</a> &nbsp; <a class="qindex" href="group__C-interface.html">C interface</a> &nbsp; </CENTER>
<HR>
@@ -0,0 +1,30 @@
/*! \page license License
RtAudio: a set of realtime audio i/o C++ classes<BR>
Copyright (c) 2001-2021 Gary P. Scavone
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.
Any person wishing to distribute modifications to the Software is
asked to send the modifications to the original developer so that
they can be incorporated into the canonical version. This is,
however, not a binding provision of this license.
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.
*/
@@ -0,0 +1,7 @@
/*! \page multi Using Simultaneous Multiple APIs
Because support for each audio API is encapsulated in a specific RtApi subclass, it is possible to compile and instantiate multiple API-specific subclasses on a given operating system. For example, one can compile both the RtApiDs and RtApiAsio classes on Windows operating systems by providing the appropriate preprocessor definitions, include files, and libraries for each. In a run-time situation, one might first attempt to determine whether any ASIO device drivers exist. This can be done by specifying the api argument RtAudio::WINDOWS_ASIO when attempting to create an instance of RtAudio. If no available devices are found, then an instance of RtAudio with the api argument RtAudio::WINDOWS_DS can be created. Alternately, if no api argument is specified, RtAudio will first look for an ASIO instance and then a DirectSound instance (on Linux systems, the default API search order is Jack, Alsa, and finally OSS). In theory, it should also be possible to have separate instances of RtAudio open at the same time with different underlying audio API support, though this has not been tested. It is difficult to know how well different audio APIs can simultaneously coexist on a given operating system. In particular, it is unlikely that the same device could be simultaneously controlled with two different audio APIs.
The static function RtAudio::getCompiledApi() is provided to determine the available compiled API support. The function RtAudio::getCurrentApi() indicates the API selected for a given RtAudio instance.
*/
@@ -0,0 +1,82 @@
/*! \page playback Playback
In this example, we provide a complete program that demonstrates the use of RtAudio for audio playback. Our program produces a two-channel sawtooth waveform for output.
\code
#include "RtAudio.h"
#include <iostream>
#include <cstdlib>
// Two-channel sawtooth wave generator.
int saw( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status, void *userData )
{
unsigned int i, j;
double *buffer = (double *) outputBuffer;
double *lastValues = (double *) userData;
if ( status )
std::cout << "Stream underflow detected!" << std::endl;
// Write interleaved audio data.
for ( i=0; i<nBufferFrames; i++ ) {
for ( j=0; j<2; j++ ) {
*buffer++ = lastValues[j];
lastValues[j] += 0.005 * (j+1+(j*0.1));
if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;
}
}
return 0;
}
int main()
{
RtAudio dac;
if ( dac.getDeviceCount() < 1 ) {
std::cout << "\nNo audio devices found!\n";
exit( 0 );
}
RtAudio::StreamParameters parameters;
parameters.deviceId = dac.getDefaultOutputDevice();
parameters.nChannels = 2;
parameters.firstChannel = 0;
unsigned int sampleRate = 44100;
unsigned int bufferFrames = 256; // 256 sample frames
double data[2] = {0, 0};
try {
dac.openStream( &parameters, NULL, RTAUDIO_FLOAT64,
sampleRate, &bufferFrames, &saw, (void *)&data );
dac.startStream();
}
catch ( RtAudioError& e ) {
e.printMessage();
exit( 0 );
}
char input;
std::cout << "\nPlaying ... press <enter> to quit.\n";
std::cin.get( input );
try {
// Stop the stream
dac.stopStream();
}
catch (RtAudioError& e) {
e.printMessage();
}
if ( dac.isStreamOpen() ) dac.closeStream();
return 0;
}
\endcode
We open the stream in exactly the same way as the previous example (except with a data format change) and specify the address of our callback function \e "saw()". The callback function will automatically be invoked when the underlying audio system needs data for output. Note that the callback function is called only when the stream is "running" (between calls to the RtAudio::startStream() and RtAudio::stopStream() functions). We can also pass a pointer value to the RtAudio::openStream() function that is made available in the callback function. In this way, it is possible to gain access to arbitrary data created in our \e main() function from within the globally defined callback function.
In this example, we stop the stream with an explicit call to RtAudio::stopStream(). It is also possible to stop a stream by returning a non-zero value from the callback function. A return value of 1 will cause the stream to finish draining its internal buffers and then halt (equivalent to calling the RtAudio::stopStream() function). A return value of 2 will cause the stream to stop immediately (equivalent to calling the RtAudio::abortStream() function).
*/
@@ -0,0 +1,73 @@
/*! \page probe Probing Device Capabilities
A programmer may wish to query the available audio device capabilities before deciding which to use. The following example outlines how this can be done.
\code
// audioprobe.cpp
#include <iostream>
#include "RtAudio.h"
int main()
{
RtAudio audio;
// Determine the number of devices available
unsigned int devices = audio.getDeviceCount();
// Scan through devices for various capabilities
RtAudio::DeviceInfo info;
for ( unsigned int i=0; i<devices; i++ ) {
info = audio.getDeviceInfo( i );
if ( info.probed == true ) {
// Print, for example, the maximum number of output channels for each device
std::cout << "device = " << i;
std::cout << ": maximum output channels = " << info.outputChannels << "\n";
}
}
return 0;
}
\endcode
The RtAudio::DeviceInfo structure is defined in RtAudio.h and provides a variety of information useful in assessing the capabilities of a device:
\code
typedef struct RtAudio::DeviceInfo {
bool probed; // true if the device capabilities were successfully probed.
std::string name; // Character string device identifier.
unsigned int outputChannels; // Maximum output channels supported by device.
unsigned int inputChannels; // Maximum input channels supported by device.
unsigned int duplexChannels; // Maximum simultaneous input/output channels supported by device.
bool isDefaultOutput; // true if this is the default output device.
bool isDefaultInput; // true if this is the default input device.
std::vector<unsigned int> sampleRates; // Supported sample rates.
unsigned int preferredSampleRate; // Preferred sample rate, e.g. for WASAPI the system sample rate.
RtAudioFormat nativeFormats; // Bit mask of supported data formats.
};
\endcode
The following data formats are defined and fully supported by RtAudio:
\code
typedef unsigned long RtAudioFormat;
static const RtAudioFormat RTAUDIO_SINT8 = 0x1; // 8-bit signed integer.
static const RtAudioFormat RTAUDIO_SINT16 = 0x2; // 16-bit signed integer.
static const RtAudioFormat RTAUDIO_SINT24 = 0x4; // 24-bit signed integer.
static const RtAudioFormat RTAUDIO_SINT32 = 0x8; // 32-bit signed integer.
static const RtAudioFormat RTAUDIO_FLOAT32 = 0x10; // Normalized between plus/minus 1.0.
static const RtAudioFormat RTAUDIO_FLOAT64 = 0x20; // Normalized between plus/minus 1.0.
\endcode
The \c nativeFormats member of the RtAudio::DeviceInfo structure is a bit mask of the above formats which are natively supported by the device. However, RtAudio will automatically provide format conversion if a particular format is not natively supported. When the \c probed member of the RtAudio::DeviceInfo structure is false, the remaining structure members are undefined and the device is probably unusable.
Some audio devices may require a minimum channel value greater than one. RtAudio will provide automatic channel number compensation when the number of channels set by the user is less than that required by the device. Channel compensation is <I>NOT</I> possible when the number of channels set by the user is greater than that supported by the device.
Note that the device enumeration is system specific and will change if any devices are plugged or unplugged by the user. Thus, the device numbers should be verified immediately before opening a stream. As well, if a user unplugs a device while an open stream is using that device, the resulting stream behaviour will be undefined (a system error will likely be generated).
Also, the capabilities reported by a device driver or underlying audio API are not always accurate and/or may be dependent on a combination of device settings. For this reason, RtAudio does not rely on the queried values when attempting to open a stream.
*/
@@ -0,0 +1,68 @@
/*! \page recording Recording
Using RtAudio for audio input is almost identical to the way it is used for playback. Here's the blocking playback example rewritten for recording:
\code
#include "RtAudio.h"
#include <iostream>
#include <cstdlib>
#include <cstring>
int record( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status, void *userData )
{
if ( status )
std::cout << "Stream overflow detected!" << std::endl;
// Do something with the data in the "inputBuffer" buffer.
return 0;
}
int main()
{
RtAudio adc;
if ( adc.getDeviceCount() < 1 ) {
std::cout << "\nNo audio devices found!\n";
exit( 0 );
}
RtAudio::StreamParameters parameters;
parameters.deviceId = adc.getDefaultInputDevice();
parameters.nChannels = 2;
parameters.firstChannel = 0;
unsigned int sampleRate = 44100;
unsigned int bufferFrames = 256; // 256 sample frames
try {
adc.openStream( NULL, &parameters, RTAUDIO_SINT16,
sampleRate, &bufferFrames, &record );
adc.startStream();
}
catch ( RtAudioError& e ) {
e.printMessage();
exit( 0 );
}
char input;
std::cout << "\nRecording ... press <enter> to quit.\n";
std::cin.get( input );
try {
// Stop the stream
adc.stopStream();
}
catch (RtAudioError& e) {
e.printMessage();
}
if ( adc.isStreamOpen() ) adc.closeStream();
return 0;
}
\endcode
In this example, we pass the address of the stream parameter structure as the second argument of the RtAudio::openStream() function and pass a NULL value for the output stream parameters. In this example, the \e record() callback function performs no specific operations.
*/
@@ -0,0 +1,48 @@
/*! \page settings Device Settings
The next step in using RtAudio is to open a stream with particular device and parameter settings.
\code
#include "RtAudio.h"
int main()
{
RtAudio dac;
if ( dac.getDeviceCount() == 0 ) exit( 0 );
RtAudio::StreamParameters parameters;
parameters.deviceId = dac.getDefaultOutputDevice();
parameters.nChannels = 2;
unsigned int sampleRate = 44100;
unsigned int bufferFrames = 256; // 256 sample frames
RtAudio::StreamOptions options;
options.flags = RTAUDIO_NONINTERLEAVED;
try {
dac.openStream( &parameters, NULL, RTAUDIO_FLOAT32,
sampleRate, &bufferFrames, &myCallback, NULL, &options );
}
catch ( RtAudioError& e ) {
std::cout << '\n' << e.getMessage() << '\n' << std::endl;
exit( 0 );
}
return 0;
}
\endcode
The RtAudio::openStream() function attempts to open a stream with a specified set of parameter values. In the above example, we attempt to open a two channel playback stream using the default output device, 32-bit floating point data, a sample rate of 44100 Hz, and a frame rate of 256 sample frames per output buffer. If the user specifies an invalid parameter value (such as a device id greater than or equal to the number of enumerated devices), an RtAudioError is thrown of type = INVALID_USE. If a system error occurs or the device does not support the specified parameter values, an RtAudioError of type = SYSTEM_ERROR is thrown. In either case, a descriptive error message is bundled with the exception and can be queried with the RtAudioError::getMessage() or RtAudioError::what() functions.
RtAudio provides four signed integer and two floating point data formats which can be specified using the RtAudioFormat parameter values mentioned earlier. If the opened device does not natively support the given format, RtAudio will automatically perform the necessary data format conversion.
The \c bufferFrames parameter specifies the desired number of sample frames that will be written to and/or read from a device per write/read operation. This parameter can be used to control stream latency though there is no guarantee that the passed value will be that used by a device. In general, a lower \c bufferFrames value will produce less latency but perhaps less robust performance. A value of zero can be specified, in which case the smallest allowable value will be used. The \c bufferFrames parameter is passed as a pointer and the actual value used by the stream is set during the device setup procedure. \c bufferFrames values should be a power of two. Optimal and allowable buffer values tend to vary between systems and devices. Stream latency can also be controlled via the optional RtAudio::StreamOptions member \c numberOfBuffers (not used in the example above), though this tends to be more system dependent. In particular, the \c numberOfBuffers parameter is ignored when using the OS-X Core Audio, Jack, and the Windows ASIO APIs.
As noted earlier, the device capabilities reported by a driver or underlying audio API are not always accurate and/or may be dependent on a combination of device settings. Because of this, RtAudio does not attempt to query a device's capabilities or use previously reported values when opening a device. Instead, RtAudio simply attempts to set the given parameters on a specified device and then checks whether the setup is successful or not.
The RtAudioCallback parameter above is a pointer to a user-defined function that will be called whenever the audio system is ready for new output data or has new input data to be read. Further details on the use of a callback function are provided in the next section.
Several stream options are available to fine-tune the behavior of an audio stream. In the example above, we specify that data will be written by the user in a \e non-interleaved format via the RtAudio::StreamOptions member \c flags. That is, all \c bufferFrames of the first channel should be written consecutively, followed by all \c bufferFrames of the second channel. By default (when no option is specified), RtAudio expects data to be written in an \e interleaved format.
*/
@@ -0,0 +1,48 @@
/*! \mainpage The RtAudio Home Page
RtAudio is a set of C++ classes that provide a common API (Application Programming Interface) for realtime audio input/output across Linux, Macintosh OS-X and Windows operating systems. RtAudio significantly simplifies the process of interacting with computer audio hardware. It was designed with the following objectives:
- object-oriented C++ design
- simple, common API across all supported platforms
- only one source and one header file for easy inclusion in programming projects
- allow simultaneous multi-api support
- support dynamic connection of devices
- provide extensive audio device parameter control
- allow audio device capability probing
- automatic internal conversion for data format, channel number compensation, (de)interleaving, and byte-swapping
RtAudio incorporates the concept of audio streams, which represent audio output (playback) and/or input (recording). Available audio devices and their capabilities can be enumerated and then specified when opening a stream. Where applicable, multiple API support can be compiled and a particular API specified when creating an RtAudio instance. See the \ref apinotes section for information specific to each of the supported audio APIs.
\section whatsnew Latest Updates (Version 5.2.0)
Changes in this release include:
- update to audioprobe.cpp to list devices for all APIs
- miscellaneous build system updates
- PulseAudio device detection fixes
- various WASAPI updates (thanks to Marcus Tomlinson)
- see git history for complete list of changes
\section download Download
Latest Release (15 November 2021): <A href="http://www.music.mcgill.ca/~gary/rtaudio/release/rtaudio-5.2.0.tar.gz">Version 5.2.0</A>
\section documentation Documentation Links
-# \ref errors
-# \ref probe
-# \ref settings
-# \ref playback
-# \ref recording
-# \ref duplex
-# \ref multi
-# \ref compiling
-# \ref apinotes
-# \ref acknowledge
-# \ref license
-# <A href="http://github.com/thestk/rtaudio">RtAudio on GitHub</A>
*/
-# <A href="bugs.html">Bug Tracker (out of date)</A>
-# <A href="updates.html">Possible Updates (out of date)</A>
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

@@ -0,0 +1,10 @@
doxygen_images = files('ccrma.gif',
'mcgill.gif')
foreach f : doxygen_images
df = configure_file(input: f,
output: '@PLAINNAME@',
copy: true,
install: get_option('install_docs'),
install_dir : get_option('datadir') / 'doc' / 'rtaudio')
endforeach
@@ -0,0 +1,22 @@
if get_option('docs')
doxygen = find_program('doxygen')
conf_data = configuration_data()
conf_data.set('PACKAGE_VERSION', meson.project_version())
conf_data.set('top_srcdir', meson.project_source_root())
conf_data.set('top_builddir', meson.project_build_root())
doxyfile = configure_file(input : 'Doxyfile.in',
output : 'Doxyfile',
configuration : conf_data,
install: false)
doxygen_target = custom_target('doc',
input: doxyfile,
output: 'html',
command: [doxygen, doxyfile],
install: get_option('install_docs'),
install_dir: get_option('datadir') / 'doc' / 'rtaudio')
subdir('images')
endif
@@ -0,0 +1,201 @@
RtAudio - a set of C++ classes that provide a common API for realtime audio input/output across Linux (native ALSA, JACK, PulseAudio, and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound, ASIO and WASAPI) operating systems.
By Gary P. Scavone, 2001-2021.
v.5.2.0: (15 November 2021)
- see git history for complete list of changes
- update to audioprobe.cpp to list devices for all APIs
- miscellaneous build system updates
- PulseAudio device detection fixes
- some Wasapi additions / fixes
v.5.1.0: (17 April 2019)
- see git history for complete list of changes
- many WASAPI updates (thanks to Marcus Tomlinson)
- miscellaneous build system updates
- bug fix for stream ticking in OS-X if using two devices for duplex
- ALSA stream handle bug fixes
- new C API wrapper
- new static functions to get API names
v5.0.0: (30 August 2017)
- see git history for complete list of changes
- WASAPI updates (thanks to Marcus Tomlinson)
- minor exception semantic changes
- miscellaneous build system updates
v4.1.2: (22 February 2016)
- added more complete automake support (thanks to Stephen Sinclair)
- miscellaneous small fixes and updates, see github repo commit history for details
v4.1.1: (26 April 2014)
- updates to WASAPI API for MinGW compiling
- WASAPI bug fixes for audio INPUT mode
- DirectSound bug fix for INPUT mode
- Bug fixes in Core, Jack, ASIO and DS for internal draining in INPUT mode
- updates to test programs for default device specifiers
- CMake buildfile update for WASAPI
- new setStreamTime function
v4.1.0: (10 April 2014)
- RtError class renamed RtAudioError and embedded in RtAudio.h (RtError.h deleted)
- new support for the Windows WASAPI API (thanks to Marcus Tomlinson)
- CMake support (thanks to Berkus Decker)
- pulse audio update to support bufferFrames argument with audio input (thanks to Jonatan Wallmander)
- fixes for ALSA API to avoid high CPU usage during stops and to clear stale data before input (thanks to Pluto Hades)
- miscellaneous efficiency updates suggested by Martin Koegler
- bug fix for OS-X xrun reporting problem
- bug fix related to error when opening a stream after closing a previously open stream
v4.0.12: (16 April 2013)
- new functionality to allow error reporting via a client-supplied function (thanks to Pavel Mogilevskiy)
- new function to return the version number
- updated RtAudio.cpp and ASIO files for UNICODE support (thanks to Renaud Schoonbroodt)
- updates to PulseAudio API support (thanks to Peter Meerwald and Tristan Matthews)
- updates for pkg-config support in configure script
- 24-bit format changed to true 24-bit format, not sub-bytes of 32-bits (thanks to Marc Britton)
- bug fixes to make sure stream status is closed if error during probeDeviceOpen
- updates / fixes to SCHED_RR code in ALSA (thanks to Marc Lindahl)
- various changes to avoid global variables (thanks to Martin Koegler)
v4.0.11: (14 June 2012)
- fixes for memory leaks in ALSA (thanks to Martin Koegler)
- PulseAudio API support added (thanks to Peter Meerwald and Tristan Matthews)
- bitwise format flag fixes in OS-X (Benjamin Schroeder and Stefan Arisona)
- changes to stopStream / drain flag to avoid hung state in ASIO, DS, OS-X, and Jack APIs (Rasmus Ekman and Carlos Luna)
v4.0.10: (30 August 2011)
- fix for compile bug in Windows DS (counting devices)
- update to configure and library Makefile
v4.0.9: (14 August 2011)
- fix for ASIO problem enumerating devices after opening duplex stream (Oliver Larkin)
- fix for OS-X problems setting sample rate and bits-per-sample
- updates for OS-X "Lion"
- updates for wide character support in Windows DS (UNICODE)
- fix for possible ALSA callback thread hang (thanks to Tristan Matthews)
- fix for DS getDeviceCount bug (vector erase problem)
v4.0.8: (12 April 2011)
- fix for MinGW4 problem enumerating and setting sample rates (iasiothiscallresolver, Dmitry Kostjuchenko)
- fix for OS-X problem handling device names in some languages (CFString conversion, Vincent Bénony)
- small change to OS-X mutex lock location to avoid lockups
- correction to documentation regarding 24-bit data (should be lower 3 bytes, not upper 3 bytes)
- bug fix for error handling of warnings (Antoine Lefebvre)
- added option to use the ALSA "default" device (Tristan Matthews)
- removed use of mutexes in Windows
- fix for ASIO4ALL behavior when stopping/closing streams (Antoine Lefebvre)
- included python binding in "contrib" directory (beta, Antoine Lefebvre)
v4.0.7: (4 February 2010)
- revised Windows DS code and device enumeration to speed up device queries
- OS-X 10.6 updates for deprecated functions
- updates to Jack shutdown code to avoid lockup
v4.0.6: (3 June 2009)
- bug fix in ALSA code to set period size to power of two (thanks to Joakim Karrstrom)
- bug fix in OS-X for OS < 10.5 ... need preprocessor definition around new variable type (thanks to Tristan Matthews)
v4.0.5: (2 February 2009)
- added support in CoreAudio for arbitrary stream channel configurations
- added getStreamSampleRate() function because the actual sample rate can sometimes vary slightly from the specified one (thanks to Theo Veenker)
- added new StreamOptions flag "RTAUDIO_SCHEDULE_REALTIME" and attribute "priority" to StreamOptions (thanks to Theo Veenker)
- replaced usleep(50000) in callbackEvent() by a wait on condition variable which gets signaled in startStream() (thanks to Theo Veenker)
- fix for Jack API when user callback function signals stop or abort calls
- fix to way stream state is changed to avoid infinite loop problem
- fix to int<->float conversion in convertBuffer() (thanks to Theo Veenker)
- bug fix in byteSwapBuffer() (thanks to Stefan Muller Arisona and Theo Veenker)
- fixed a few gcc 4.4 errors in OS-X
- fixed bug in rtaudio-config script
- revised configure script and Makefile structures
- 64-bit fixes in ALSA API (thanks to Stefan Muller Arisona)
- fixed ASIO sample rate selection bug (thanks to Sasha Zheligovsky)
v4.0.4: (24 January 2008)
- added functionality to allow getDeviceInfo() to work in ALSA for an open device (like ASIO)
- fixes in configure script
- fixed clearing of error message stream in error()
- fixed RtAudio::DeviceInfo description in "probing" documentation
- memory leak fixes in ALSA and OSS
- Jack in/out port flag fix
- Windows changes for thread priority and GLOBALFOCUS
v4.0.3: (7 December 2007)
- added support for MinGW compiler to configure script
- a few MinGW-related changes to RtAudio.cpp
- renamed test program probe.cpp to audioprobe.cpp
- moved various header files into single "include" directory and updated VC++ project files
v4.0.2: (21 August 2007)
- fix to RtError::WARNING typo in RtAudio.h (RtApiDummy)
- removed "+1"s in RtApiCore c++ append when getting device name
v4.0.1: (13 August 2007)
- fix to RtError::WARNING typo in RtAudio.cpp
v4.0.0: (7 August 2007)
- new support for non-interleaved user data
- additional input/output parameter specifications, including channel offset
- new support for dynamic connection of devices
- new support for stream time
- revised callback arguments, including separate input and output buffer arguments
- revised C++ exception handling
- revised OSS support for version 4.0
- discontinued support of blocking functionality
- discontinued support of SGI
- Windows DirectSound API bug fix
- NetBSD support (using OSS API) by Emmanuel Dreyfus
- changed default pthread scheduling priority to SCHED_RR when defined in the system
- new getCompiledApi() static function
- new getCurrentApi(), getStreamTime(), getStreamLatency(), and isStreamRunning() functions
- modified RtAudioDeviceInfo structure to distinguish default input and output devices
v3.0.3: (18 November 2005)
- UNICODE fix for Windows DirectSound API
- MinGW compiler fix for ASIO API
v3.0.2: (14 October 2005)
- modification of ALSA read/write order to fix duplex under/overruns
- added synchronization of input/output devices for ALSA duplex operation
- cleaned up and improved error reporting throughout
- bug fix in Windows DirectSound support for 8-bit audio
- bug fix in Windows DirectSound support during device capture query
- added ASIOOutputReady() call near end of callbackEvent to fix some driver behavior
- added #include <stdio.h> to RtAudio.cpp
- fixed bug in RtApiCore for duplex operation with different I/O devices
- improvements to DirectX pointer chasing (by Robin Davies)
- backdoor RtDsStatistics hook provides DirectX performance information (by Robin Davies)
- bug fix for non-power-of-two Asio granularity used by Edirol PCR-A30 (by Robin Davies)
- auto-call CoInitialize for DSOUND and ASIO platforms (by Robin Davies)
v3.0.1: (22 March 2004)
- bug fix in Windows DirectSound support for cards with output only
v3.0: (11 March 2004)
- added Linux Jack audio server support
- new multi-api support by subclassing all apis and making rtaudio a controller class
- added over/underload check to Mac OS X support
- new scheme for blocking functionality in callback-based apis (CoreAudio, ASIO, and JACK)
- removed multiple stream support (all stream identifier arguments removed)
- various style and name changes to conform with standard C++ practice
v2.1.1: (24 October 2002)
- bug fix in duplex for Mac OS X and Windows ASIO code
- duplex example change in tutorial
v2.1: (7 October 2002)
- added Mac OS X CoreAudio support
- added Windows ASIO support
- API change to getDeviceInfo(): device argument must be an integer between 1 - getDeviceCount().
- "configure" support added for unix systems
- adopted MIT-like license
- various internal structural changes and bug fixes
v2.01: (27 April 2002)
- Windows destructor bug fix when no devices available
- RtAudioError class renamed to RtError
- Preprocessor definitions changed slightly (i.e. __LINUX_OSS_ to __LINUX_OSS__) to conform with new Synthesis ToolKit distribution
v2.0: (22 January 2002)
- first release of new independent class
@@ -0,0 +1,257 @@
/*
Steinberg Audio Stream I/O API
(c) 1996, Steinberg Soft- und Hardware GmbH
asio.cpp
asio functions entries which translate the
asio interface to the asiodrvr class methods
*/
#include <string.h>
#include "asiosys.h" // platform definition
#include "asio.h"
#if MAC
#include "asiodrvr.h"
#pragma export on
AsioDriver *theAsioDriver = 0;
extern "C"
{
long main()
{
return 'ASIO';
}
#elif WINDOWS
#include "windows.h"
#include "iasiodrv.h"
#include "asiodrivers.h"
IASIO *theAsioDriver = 0;
extern AsioDrivers *asioDrivers;
#elif SGI || SUN || BEOS || LINUX
#include "asiodrvr.h"
static AsioDriver *theAsioDriver = 0;
#endif
//-----------------------------------------------------------------------------------------------------
ASIOError ASIOInit(ASIODriverInfo *info)
{
#if MAC || SGI || SUN || BEOS || LINUX
if(theAsioDriver)
{
delete theAsioDriver;
theAsioDriver = 0;
}
info->driverVersion = 0;
strcpy(info->name, "No ASIO Driver");
theAsioDriver = getDriver();
if(!theAsioDriver)
{
strcpy(info->errorMessage, "Not enough memory for the ASIO driver!");
return ASE_NotPresent;
}
if(!theAsioDriver->init(info->sysRef))
{
theAsioDriver->getErrorMessage(info->errorMessage);
delete theAsioDriver;
theAsioDriver = 0;
return ASE_NotPresent;
}
strcpy(info->errorMessage, "No ASIO Driver Error");
theAsioDriver->getDriverName(info->name);
info->driverVersion = theAsioDriver->getDriverVersion();
return ASE_OK;
#else
info->driverVersion = 0;
strcpy(info->name, "No ASIO Driver");
if(theAsioDriver) // must be loaded!
{
if(!theAsioDriver->init(info->sysRef))
{
theAsioDriver->getErrorMessage(info->errorMessage);
theAsioDriver = 0;
return ASE_NotPresent;
}
strcpy(info->errorMessage, "No ASIO Driver Error");
theAsioDriver->getDriverName(info->name);
info->driverVersion = theAsioDriver->getDriverVersion();
return ASE_OK;
}
return ASE_NotPresent;
#endif // !MAC
}
ASIOError ASIOExit(void)
{
if(theAsioDriver)
{
#if WINDOWS
asioDrivers->removeCurrentDriver();
#else
delete theAsioDriver;
#endif
}
theAsioDriver = 0;
return ASE_OK;
}
ASIOError ASIOStart(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->start();
}
ASIOError ASIOStop(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->stop();
}
ASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels)
{
if(!theAsioDriver)
{
*numInputChannels = *numOutputChannels = 0;
return ASE_NotPresent;
}
return theAsioDriver->getChannels(numInputChannels, numOutputChannels);
}
ASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency)
{
if(!theAsioDriver)
{
*inputLatency = *outputLatency = 0;
return ASE_NotPresent;
}
return theAsioDriver->getLatencies(inputLatency, outputLatency);
}
ASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity)
{
if(!theAsioDriver)
{
*minSize = *maxSize = *preferredSize = *granularity = 0;
return ASE_NotPresent;
}
return theAsioDriver->getBufferSize(minSize, maxSize, preferredSize, granularity);
}
ASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->canSampleRate(sampleRate);
}
ASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->getSampleRate(currentRate);
}
ASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->setSampleRate(sampleRate);
}
ASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources)
{
if(!theAsioDriver)
{
*numSources = 0;
return ASE_NotPresent;
}
return theAsioDriver->getClockSources(clocks, numSources);
}
ASIOError ASIOSetClockSource(long reference)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->setClockSource(reference);
}
ASIOError ASIOGetSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->getSamplePosition(sPos, tStamp);
}
ASIOError ASIOGetChannelInfo(ASIOChannelInfo *info)
{
if(!theAsioDriver)
{
info->channelGroup = -1;
info->type = ASIOSTInt16MSB;
strcpy(info->name, "None");
return ASE_NotPresent;
}
return theAsioDriver->getChannelInfo(info);
}
ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks)
{
if(!theAsioDriver)
{
ASIOBufferInfo *info = bufferInfos;
for(long i = 0; i < numChannels; i++, info++)
info->buffers[0] = info->buffers[1] = 0;
return ASE_NotPresent;
}
return theAsioDriver->createBuffers(bufferInfos, numChannels, bufferSize, callbacks);
}
ASIOError ASIODisposeBuffers(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->disposeBuffers();
}
ASIOError ASIOControlPanel(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->controlPanel();
}
ASIOError ASIOFuture(long selector, void *opt)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->future(selector, opt);
}
ASIOError ASIOOutputReady(void)
{
if(!theAsioDriver)
return ASE_NotPresent;
return theAsioDriver->outputReady();
}
#if MAC
} // extern "C"
#pragma export off
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,186 @@
#include <string.h>
#include "asiodrivers.h"
AsioDrivers* asioDrivers = 0;
bool loadAsioDriver(char *name);
bool loadAsioDriver(char *name)
{
if(!asioDrivers)
asioDrivers = new AsioDrivers();
if(asioDrivers)
return asioDrivers->loadDriver(name);
return false;
}
//------------------------------------------------------------------------------------
#if MAC
bool resolveASIO(unsigned long aconnID);
AsioDrivers::AsioDrivers() : CodeFragments("ASIO Drivers", 'AsDr', 'Asio')
{
connID = -1;
curIndex = -1;
}
AsioDrivers::~AsioDrivers()
{
removeCurrentDriver();
}
bool AsioDrivers::getCurrentDriverName(char *name)
{
if(curIndex >= 0)
return getName(curIndex, name);
return false;
}
long AsioDrivers::getDriverNames(char **names, long maxDrivers)
{
for(long i = 0; i < getNumFragments() && i < maxDrivers; i++)
getName(i, names[i]);
return getNumFragments() < maxDrivers ? getNumFragments() : maxDrivers;
}
bool AsioDrivers::loadDriver(char *name)
{
char dname[64];
unsigned long newID;
for(long i = 0; i < getNumFragments(); i++)
{
if(getName(i, dname) && !strcmp(name, dname))
{
if(newInstance(i, &newID))
{
if(resolveASIO(newID))
{
if(connID != -1)
removeInstance(curIndex, connID);
curIndex = i;
connID = newID;
return true;
}
}
break;
}
}
return false;
}
void AsioDrivers::removeCurrentDriver()
{
if(connID != -1)
removeInstance(curIndex, connID);
connID = -1;
curIndex = -1;
}
//------------------------------------------------------------------------------------
#elif WINDOWS
#include "iasiodrv.h"
extern IASIO* theAsioDriver;
AsioDrivers::AsioDrivers() : AsioDriverList()
{
curIndex = -1;
}
AsioDrivers::~AsioDrivers()
{
}
bool AsioDrivers::getCurrentDriverName(char *name)
{
if(curIndex >= 0)
return asioGetDriverName(curIndex, name, 32) == 0 ? true : false;
name[0] = 0;
return false;
}
long AsioDrivers::getDriverNames(char **names, long maxDrivers)
{
for(long i = 0; i < asioGetNumDev() && i < maxDrivers; i++)
asioGetDriverName(i, names[i], 32);
return asioGetNumDev() < maxDrivers ? asioGetNumDev() : maxDrivers;
}
bool AsioDrivers::loadDriver(char *name)
{
char dname[64];
char curName[64];
for(long i = 0; i < asioGetNumDev(); i++)
{
if(!asioGetDriverName(i, dname, 32) && !strcmp(name, dname))
{
curName[0] = 0;
getCurrentDriverName(curName); // in case we fail...
removeCurrentDriver();
if(!asioOpenDriver(i, (void **)&theAsioDriver))
{
curIndex = i;
return true;
}
else
{
theAsioDriver = 0;
if(curName[0] && strcmp(dname, curName))
loadDriver(curName); // try restore
}
break;
}
}
return false;
}
void AsioDrivers::removeCurrentDriver()
{
if(curIndex != -1)
asioCloseDriver(curIndex);
curIndex = -1;
}
#elif SGI || BEOS
#include "asiolist.h"
AsioDrivers::AsioDrivers()
: AsioDriverList()
{
curIndex = -1;
}
AsioDrivers::~AsioDrivers()
{
}
bool AsioDrivers::getCurrentDriverName(char *name)
{
return false;
}
long AsioDrivers::getDriverNames(char **names, long maxDrivers)
{
return 0;
}
bool AsioDrivers::loadDriver(char *name)
{
return false;
}
void AsioDrivers::removeCurrentDriver()
{
}
#else
#error implement me
#endif
@@ -0,0 +1,41 @@
#ifndef __AsioDrivers__
#define __AsioDrivers__
#include "ginclude.h"
#if MAC
#include "CodeFragments.hpp"
class AsioDrivers : public CodeFragments
#elif WINDOWS
#include <windows.h>
#include "asiolist.h"
class AsioDrivers : public AsioDriverList
#elif SGI || BEOS
#include "asiolist.h"
class AsioDrivers : public AsioDriverList
#else
#error implement me
#endif
{
public:
AsioDrivers();
~AsioDrivers();
bool getCurrentDriverName(char *name);
long getDriverNames(char **names, long maxDrivers);
bool loadDriver(char *name);
void removeCurrentDriver();
long getCurrentDriverIndex() {return curIndex;}
protected:
unsigned long connID;
long curIndex;
};
#endif
@@ -0,0 +1,76 @@
/*
Steinberg Audio Stream I/O API
(c) 1996, Steinberg Soft- und Hardware GmbH
charlie (May 1996)
asiodrvr.h
c++ superclass to implement asio functionality. from this,
you can derive whatever required
*/
#ifndef _asiodrvr_
#define _asiodrvr_
// cpu and os system we are running on
#include "asiosys.h"
// basic "C" interface
#include "asio.h"
class AsioDriver;
extern AsioDriver *getDriver(); // for generic constructor
#if WINDOWS
#include <windows.h>
#include "combase.h"
#include "iasiodrv.h"
class AsioDriver : public IASIO ,public CUnknown
{
public:
AsioDriver(LPUNKNOWN pUnk, HRESULT *phr);
DECLARE_IUNKNOWN
// Factory method
static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
// IUnknown
virtual HRESULT STDMETHODCALLTYPE NonDelegatingQueryInterface(REFIID riid,void **ppvObject);
#else
class AsioDriver
{
public:
AsioDriver();
#endif
virtual ~AsioDriver();
virtual ASIOBool init(void* sysRef);
virtual void getDriverName(char *name); // max 32 bytes incl. terminating zero
virtual long getDriverVersion();
virtual void getErrorMessage(char *string); // max 124 bytes incl.
virtual ASIOError start();
virtual ASIOError stop();
virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels);
virtual ASIOError getLatencies(long *inputLatency, long *outputLatency);
virtual ASIOError getBufferSize(long *minSize, long *maxSize,
long *preferredSize, long *granularity);
virtual ASIOError canSampleRate(ASIOSampleRate sampleRate);
virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate);
virtual ASIOError setSampleRate(ASIOSampleRate sampleRate);
virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources);
virtual ASIOError setClockSource(long reference);
virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp);
virtual ASIOError getChannelInfo(ASIOChannelInfo *info);
virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks);
virtual ASIOError disposeBuffers();
virtual ASIOError controlPanel();
virtual ASIOError future(long selector, void *opt);
virtual ASIOError outputReady();
};
#endif
@@ -0,0 +1,3 @@
The Steinberg ASIO SDK and licensing agreement can be found at:
- https://www.steinberg.net/developers/
@@ -0,0 +1,306 @@
#include <windows.h>
#include "iasiodrv.h"
#include "asiolist.h"
#define ASIODRV_DESC "description"
#define INPROC_SERVER "InprocServer32"
#define ASIO_PATH "software\\asio"
#define COM_CLSID "clsid"
// ******************************************************************
// Local Functions
// ******************************************************************
static LONG findDrvPath (char *clsidstr,char *dllpath,int dllpathsize)
{
HKEY hkEnum,hksub,hkpath;
char databuf[512];
LONG cr,rc = -1;
DWORD datatype,datasize;
DWORD index;
OFSTRUCT ofs;
HFILE hfile;
BOOL found = FALSE;
#ifdef UNICODE
CharLowerBuffA(clsidstr,strlen(clsidstr));
if ((cr = RegOpenKeyA(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) {
index = 0;
while (cr == ERROR_SUCCESS && !found) {
cr = RegEnumKeyA(hkEnum,index++,databuf,512);
if (cr == ERROR_SUCCESS) {
CharLowerBuffA(databuf,strlen(databuf));
if (!(strcmp(databuf,clsidstr))) {
if ((cr = RegOpenKeyExA(hkEnum,databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
if ((cr = RegOpenKeyExA(hksub,INPROC_SERVER,0,KEY_READ,&hkpath)) == ERROR_SUCCESS) {
datatype = REG_SZ; datasize = (DWORD)dllpathsize;
cr = RegQueryValueEx(hkpath,0,0,&datatype,(LPBYTE)dllpath,&datasize);
if (cr == ERROR_SUCCESS) {
memset(&ofs,0,sizeof(OFSTRUCT));
ofs.cBytes = sizeof(OFSTRUCT);
hfile = OpenFile(dllpath,&ofs,OF_EXIST);
if (hfile) rc = 0;
}
RegCloseKey(hkpath);
}
RegCloseKey(hksub);
}
found = TRUE; // break out
}
}
}
RegCloseKey(hkEnum);
}
#else
CharLowerBuff(clsidstr,strlen(clsidstr));
if ((cr = RegOpenKey(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) {
index = 0;
while (cr == ERROR_SUCCESS && !found) {
cr = RegEnumKey(hkEnum,index++,databuf,512);
if (cr == ERROR_SUCCESS) {
CharLowerBuff(databuf,strlen(databuf));
if (!(strcmp(databuf,clsidstr))) {
if ((cr = RegOpenKeyEx(hkEnum,databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
if ((cr = RegOpenKeyEx(hksub,INPROC_SERVER,0,KEY_READ,&hkpath)) == ERROR_SUCCESS) {
datatype = REG_SZ; datasize = (DWORD)dllpathsize;
cr = RegQueryValueEx(hkpath,0,0,&datatype,(LPBYTE)dllpath,&datasize);
if (cr == ERROR_SUCCESS) {
memset(&ofs,0,sizeof(OFSTRUCT));
ofs.cBytes = sizeof(OFSTRUCT);
hfile = OpenFile(dllpath,&ofs,OF_EXIST);
if (hfile) rc = 0;
}
RegCloseKey(hkpath);
}
RegCloseKey(hksub);
}
found = TRUE; // break out
}
}
}
RegCloseKey(hkEnum);
}
#endif
return rc;
}
static LPASIODRVSTRUCT newDrvStruct (HKEY hkey,char *keyname,int drvID,LPASIODRVSTRUCT lpdrv)
{
HKEY hksub;
char databuf[256];
char dllpath[MAXPATHLEN];
WORD wData[100];
CLSID clsid;
DWORD datatype,datasize;
LONG cr,rc;
if (!lpdrv) {
if ((cr = RegOpenKeyExA(hkey,keyname,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
datatype = REG_SZ; datasize = 256;
cr = RegQueryValueExA(hksub,COM_CLSID,0,&datatype,(LPBYTE)databuf,&datasize);
if (cr == ERROR_SUCCESS) {
rc = findDrvPath (databuf,dllpath,MAXPATHLEN);
if (rc == 0) {
lpdrv = new ASIODRVSTRUCT[1];
if (lpdrv) {
memset(lpdrv,0,sizeof(ASIODRVSTRUCT));
lpdrv->drvID = drvID;
MultiByteToWideChar(CP_ACP,0,(LPCSTR)databuf,-1,(LPWSTR)wData,100);
if ((cr = CLSIDFromString((LPOLESTR)wData,(LPCLSID)&clsid)) == S_OK) {
memcpy(&lpdrv->clsid,&clsid,sizeof(CLSID));
}
datatype = REG_SZ; datasize = 256;
cr = RegQueryValueExA(hksub,ASIODRV_DESC,0,&datatype,(LPBYTE)databuf,&datasize);
if (cr == ERROR_SUCCESS) {
strcpy(lpdrv->drvname,databuf);
}
else strcpy(lpdrv->drvname,keyname);
}
}
}
RegCloseKey(hksub);
}
}
else lpdrv->next = newDrvStruct(hkey,keyname,drvID+1,lpdrv->next);
return lpdrv;
}
static void deleteDrvStruct (LPASIODRVSTRUCT lpdrv)
{
IASIO *iasio;
if (lpdrv != 0) {
deleteDrvStruct(lpdrv->next);
if (lpdrv->asiodrv) {
iasio = (IASIO *)lpdrv->asiodrv;
iasio->Release();
}
delete lpdrv;
}
}
static LPASIODRVSTRUCT getDrvStruct (int drvID,LPASIODRVSTRUCT lpdrv)
{
while (lpdrv) {
if (lpdrv->drvID == drvID) return lpdrv;
lpdrv = lpdrv->next;
}
return 0;
}
// ******************************************************************
// ******************************************************************
// AsioDriverList
// ******************************************************************
AsioDriverList::AsioDriverList ()
{
HKEY hkEnum = 0;
char keyname[MAXDRVNAMELEN];
LPASIODRVSTRUCT pdl;
LONG cr;
DWORD index = 0;
numdrv = 0;
lpdrvlist = 0;
#ifdef UNICODE
cr = RegOpenKeyA(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum);
#else
cr = RegOpenKey(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum);
#endif
while (cr == ERROR_SUCCESS) {
#ifdef UNICODE
if ((cr = RegEnumKeyA(hkEnum,index++,keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) {
#else
if ((cr = RegEnumKey(hkEnum,index++,keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) {
#endif
lpdrvlist = newDrvStruct (hkEnum,keyname,0,lpdrvlist);
}
}
if (hkEnum) RegCloseKey(hkEnum);
pdl = lpdrvlist;
while (pdl) {
numdrv++;
pdl = pdl->next;
}
if (numdrv) CoInitialize(0); // initialize COM
}
AsioDriverList::~AsioDriverList ()
{
if (numdrv) {
deleteDrvStruct(lpdrvlist);
CoUninitialize();
}
}
LONG AsioDriverList::asioGetNumDev (VOID)
{
return (LONG)numdrv;
}
LONG AsioDriverList::asioOpenDriver (int drvID,LPVOID *asiodrv)
{
LPASIODRVSTRUCT lpdrv = 0;
long rc;
if (!asiodrv) return DRVERR_INVALID_PARAM;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
if (!lpdrv->asiodrv) {
rc = CoCreateInstance(lpdrv->clsid,0,CLSCTX_INPROC_SERVER,lpdrv->clsid,asiodrv);
if (rc == S_OK) {
lpdrv->asiodrv = *asiodrv;
return 0;
}
// else if (rc == REGDB_E_CLASSNOTREG)
// strcpy (info->messageText, "Driver not registered in the Registration Database!");
}
else rc = DRVERR_DEVICE_ALREADY_OPEN;
}
else rc = DRVERR_DEVICE_NOT_FOUND;
return rc;
}
LONG AsioDriverList::asioCloseDriver (int drvID)
{
LPASIODRVSTRUCT lpdrv = 0;
IASIO *iasio;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
if (lpdrv->asiodrv) {
iasio = (IASIO *)lpdrv->asiodrv;
iasio->Release();
lpdrv->asiodrv = 0;
}
}
return 0;
}
LONG AsioDriverList::asioGetDriverName (int drvID,char *drvname,int drvnamesize)
{
LPASIODRVSTRUCT lpdrv = 0;
if (!drvname) return DRVERR_INVALID_PARAM;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
if (strlen(lpdrv->drvname) < (unsigned int)drvnamesize) {
strcpy(drvname,lpdrv->drvname);
}
else {
memcpy(drvname,lpdrv->drvname,drvnamesize-4);
drvname[drvnamesize-4] = '.';
drvname[drvnamesize-3] = '.';
drvname[drvnamesize-2] = '.';
drvname[drvnamesize-1] = 0;
}
return 0;
}
return DRVERR_DEVICE_NOT_FOUND;
}
LONG AsioDriverList::asioGetDriverPath (int drvID,char *dllpath,int dllpathsize)
{
LPASIODRVSTRUCT lpdrv = 0;
if (!dllpath) return DRVERR_INVALID_PARAM;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
if (strlen(lpdrv->dllpath) < (unsigned int)dllpathsize) {
strcpy(dllpath,lpdrv->dllpath);
return 0;
}
dllpath[0] = 0;
return DRVERR_INVALID_PARAM;
}
return DRVERR_DEVICE_NOT_FOUND;
}
LONG AsioDriverList::asioGetDriverCLSID (int drvID,CLSID *clsid)
{
LPASIODRVSTRUCT lpdrv = 0;
if (!clsid) return DRVERR_INVALID_PARAM;
if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
memcpy(clsid,&lpdrv->clsid,sizeof(CLSID));
return 0;
}
return DRVERR_DEVICE_NOT_FOUND;
}
@@ -0,0 +1,46 @@
#ifndef __asiolist__
#define __asiolist__
#define DRVERR -5000
#define DRVERR_INVALID_PARAM DRVERR-1
#define DRVERR_DEVICE_ALREADY_OPEN DRVERR-2
#define DRVERR_DEVICE_NOT_FOUND DRVERR-3
#define MAXPATHLEN 512
#define MAXDRVNAMELEN 128
struct asiodrvstruct
{
int drvID;
CLSID clsid;
char dllpath[MAXPATHLEN];
char drvname[MAXDRVNAMELEN];
LPVOID asiodrv;
struct asiodrvstruct *next;
};
typedef struct asiodrvstruct ASIODRVSTRUCT;
typedef ASIODRVSTRUCT *LPASIODRVSTRUCT;
class AsioDriverList {
public:
AsioDriverList();
~AsioDriverList();
LONG asioOpenDriver (int,VOID **);
LONG asioCloseDriver (int);
// nice to have
LONG asioGetNumDev (VOID);
LONG asioGetDriverName (int,char *,int);
LONG asioGetDriverPath (int,char *,int);
LONG asioGetDriverCLSID (int,CLSID *);
// or use directly access
LPASIODRVSTRUCT lpdrvlist;
int numdrv;
};
typedef class AsioDriverList *LPASIODRIVERLIST;
#endif
@@ -0,0 +1,82 @@
#ifndef __asiosys__
#define __asiosys__
#if defined(_WIN32) || defined(_WIN64)
#undef MAC
#define PPC 0
#define WINDOWS 1
#define SGI 0
#define SUN 0
#define LINUX 0
#define BEOS 0
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#elif BEOS
#define MAC 0
#define PPC 0
#define WINDOWS 0
#define PC 0
#define SGI 0
#define SUN 0
#define LINUX 0
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#ifndef DEBUG
#define DEBUG 0
#if DEBUG
void DEBUGGERMESSAGE(char *string);
#else
#define DEBUGGERMESSAGE(a)
#endif
#endif
#elif SGI
#define MAC 0
#define PPC 0
#define WINDOWS 0
#define PC 0
#define SUN 0
#define LINUX 0
#define BEOS 0
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#ifndef DEBUG
#define DEBUG 0
#if DEBUG
void DEBUGGERMESSAGE(char *string);
#else
#define DEBUGGERMESSAGE(a)
#endif
#endif
#else // MAC
#define MAC 1
#define PPC 1
#define WINDOWS 0
#define PC 0
#define SGI 0
#define SUN 0
#define LINUX 0
#define BEOS 0
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#ifndef DEBUG
#define DEBUG 0
#if DEBUG
void DEBUGGERMESSAGE(char *string);
#else
#define DEBUGGERMESSAGE(a)
#endif
#endif
#endif
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,212 @@
#pragma once
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
devpkey.h
Abstract:
Defines property keys for the Plug and Play Device Property API.
Author:
Jim Cavalaris (jamesca) 10-14-2003
Environment:
User-mode only.
Revision History:
14-October-2003 jamesca
Creation and initial implementation.
20-June-2006 dougb
Copied Jim's version replaced "DEFINE_DEVPROPKEY(DEVPKEY_" with "DEFINE_PROPERTYKEY(PKEY_"
--*/
//#include <devpropdef.h>
//
// _NAME
//
DEFINE_PROPERTYKEY(PKEY_NAME, 0xb725f130, 0x47ef, 0x101a, 0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac, 10); // DEVPROP_TYPE_STRING
//
// Device properties
// These PKEYs correspond to the old setupapi SPDRP_XXX properties
//
DEFINE_PROPERTYKEY(PKEY_Device_DeviceDesc, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 2); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_HardwareIds, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 3); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_CompatibleIds, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 4); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_Service, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 6); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_Class, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 9); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_ClassGuid, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 10); // DEVPROP_TYPE_GUID
DEFINE_PROPERTYKEY(PKEY_Device_Driver, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 11); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_ConfigFlags, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 12); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_Manufacturer, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 13); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_LocationInfo, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 15); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_PDOName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 16); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_Capabilities, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 17); // DEVPROP_TYPE_UNINT32
DEFINE_PROPERTYKEY(PKEY_Device_UINumber, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 18); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_UpperFilters, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 19); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_LowerFilters, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 20); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_BusTypeGuid, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 21); // DEVPROP_TYPE_GUID
DEFINE_PROPERTYKEY(PKEY_Device_LegacyBusType, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 22); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_BusNumber, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 23); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_EnumeratorName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 24); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_Security, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 25); // DEVPROP_TYPE_SECURITY_DESCRIPTOR
DEFINE_PROPERTYKEY(PKEY_Device_SecuritySDS, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 26); // DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DevType, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 27); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_Exclusive, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 28); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_Characteristics, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 29); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_Address, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 30); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_UINumberDescFormat, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 31); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_PowerData, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 32); // DEVPROP_TYPE_BINARY
DEFINE_PROPERTYKEY(PKEY_Device_RemovalPolicy, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 33); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_RemovalPolicyDefault, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 34); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_RemovalPolicyOverride, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 35); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_InstallState, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 36); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_LocationPaths, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 37); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_BaseContainerId, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 38); // DEVPROP_TYPE_GUID
//
// Device properties
// These PKEYs correspond to a device's status and problem code
//
DEFINE_PROPERTYKEY(PKEY_Device_DevNodeStatus, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 2); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_ProblemCode, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 3); // DEVPROP_TYPE_UINT32
//
// Device properties
// These PKEYs correspond to device relations
//
DEFINE_PROPERTYKEY(PKEY_Device_EjectionRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 4); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_RemovalRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 5); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_PowerRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 6); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_BusRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 7); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_Parent, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 8); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_Children, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 9); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_Siblings, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 10); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_TransportRelations, 0x4340a6c5, 0x93fa, 0x4706, 0x97, 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 11); // DEVPROP_TYPE_STRING_LIST
//
// Other Device properties
//
DEFINE_PROPERTYKEY(PKEY_Device_Reported, 0x80497100, 0x8c73, 0x48b9, 0xaa, 0xd9, 0xce, 0x38, 0x7e, 0x19, 0xc5, 0x6e, 2); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_Device_Legacy, 0x80497100, 0x8c73, 0x48b9, 0xaa, 0xd9, 0xce, 0x38, 0x7e, 0x19, 0xc5, 0x6e, 3); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_Device_InstanceId, 0x78c34fc8, 0x104a, 0x4aca, 0x9e, 0xa4, 0x52, 0x4d, 0x52, 0x99, 0x6e, 0x57, 256); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_ContainerId, 0x8c7ed206, 0x3f8a, 0x4827, 0xb3, 0xab, 0xae, 0x9e, 0x1f, 0xae, 0xfc, 0x6c, 2); // DEVPROP_TYPE_GUID
DEFINE_PROPERTYKEY(PKEY_Device_ModelId, 0x80d81ea6, 0x7473, 0x4b0c, 0x82, 0x16, 0xef, 0xc1, 0x1a, 0x2c, 0x4c, 0x8b, 2); // DEVPROP_TYPE_GUID
DEFINE_PROPERTYKEY(PKEY_Device_FriendlyNameAttributes, 0x80d81ea6, 0x7473, 0x4b0c, 0x82, 0x16, 0xef, 0xc1, 0x1a, 0x2c, 0x4c, 0x8b, 3); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_ManufacturerAttributes, 0x80d81ea6, 0x7473, 0x4b0c, 0x82, 0x16, 0xef, 0xc1, 0x1a, 0x2c, 0x4c, 0x8b, 4); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_PresenceNotForDevice, 0x80d81ea6, 0x7473, 0x4b0c, 0x82, 0x16, 0xef, 0xc1, 0x1a, 0x2c, 0x4c, 0x8b, 5); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_Numa_Proximity_Domain, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 1); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_DHP_Rebalance_Policy, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 2); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_Numa_Node, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 3); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_BusReportedDeviceDesc, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 4); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_InstallInProgress, 0x83da6326, 0x97a6, 0x4088, 0x94, 0x53, 0xa1, 0x92, 0x3f, 0x57, 0x3b, 0x29, 9); // DEVPROP_TYPE_BOOLEAN
//
// Device driver properties
//
DEFINE_PROPERTYKEY(PKEY_Device_DriverDate, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 2); // DEVPROP_TYPE_FILETIME
DEFINE_PROPERTYKEY(PKEY_Device_DriverVersion, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 3); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverDesc, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 4); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverInfPath, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 5); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverInfSection, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 6); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverInfSectionExt, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 7); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_MatchingDeviceId, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 8); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverProvider, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 9); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverPropPageProvider, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 10); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverCoInstallers, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 11); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_Device_ResourcePickerTags, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 12); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_ResourcePickerExceptions, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 13); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_Device_DriverRank, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 14); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_DriverLogoLevel, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 15); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_Device_NoConnectSound, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 17); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_Device_GenericDriverInstalled, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 18); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_Device_AdditionalSoftwareRequested, 0xa8b865dd, 0x2e3d, 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 19);// DEVPROP_TYPE_BOOLEAN
//
// Device safe-removal properties
//
DEFINE_PROPERTYKEY(PKEY_Device_SafeRemovalRequired, 0xafd97640, 0x86a3, 0x4210, 0xb6, 0x7c, 0x28, 0x9c, 0x41, 0xaa, 0xbe, 0x55, 2); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_Device_SafeRemovalRequiredOverride, 0xafd97640, 0x86a3, 0x4210, 0xb6, 0x7c, 0x28, 0x9c, 0x41, 0xaa, 0xbe, 0x55, 3);// DEVPROP_TYPE_BOOLEAN
//
// Device properties that were set by the driver package that was installed
// on the device.
//
DEFINE_PROPERTYKEY(PKEY_DrvPkg_Model, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 2); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DrvPkg_VendorWebSite, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 3); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DrvPkg_DetailedDescription, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 4); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DrvPkg_DocumentationLink, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 5); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DrvPkg_Icon, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 6); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_DrvPkg_BrandingIcon, 0xcf73bb51, 0x3abf, 0x44a2, 0x85, 0xe0, 0x9a, 0x3d, 0xc7, 0xa1, 0x21, 0x32, 7); // DEVPROP_TYPE_STRING_LIST
//
// Device setup class properties
// These PKEYs correspond to the old setupapi SPCRP_XXX properties
//
DEFINE_PROPERTYKEY(PKEY_DeviceClass_UpperFilters, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 19); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_DeviceClass_LowerFilters, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 20); // DEVPROP_TYPE_STRING_LIST
DEFINE_PROPERTYKEY(PKEY_DeviceClass_Security, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 25); // DEVPROP_TYPE_SECURITY_DESCRIPTOR
DEFINE_PROPERTYKEY(PKEY_DeviceClass_SecuritySDS, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 26); // DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceClass_DevType, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 27); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_DeviceClass_Exclusive, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 28); // DEVPROP_TYPE_UINT32
DEFINE_PROPERTYKEY(PKEY_DeviceClass_Characteristics, 0x4321918b, 0xf69e, 0x470d, 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b, 29); // DEVPROP_TYPE_UINT32
//
// Device setup class properties
// These PKEYs correspond to registry values under the device class GUID key
//
DEFINE_PROPERTYKEY(PKEY_DeviceClass_Name, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 2); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceClass_ClassName, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 3); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceClass_Icon, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 4); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceClass_ClassInstaller, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 5); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceClass_PropPageProvider, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 6); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceClass_NoInstallClass, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 7); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_DeviceClass_NoDisplayClass, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 8); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_DeviceClass_SilentInstall, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 9); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_DeviceClass_NoUseClass, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 10); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_DeviceClass_DefaultService, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 11); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceClass_IconPath, 0x259abffc, 0x50a7, 0x47ce, 0xaf, 0x8, 0x68, 0xc9, 0xa7, 0xd7, 0x33, 0x66, 12); // DEVPROP_TYPE_STRING_LIST
//
// Other Device setup class properties
//
DEFINE_PROPERTYKEY(PKEY_DeviceClass_ClassCoInstallers, 0x713d1703, 0xa2e2, 0x49f5, 0x92, 0x14, 0x56, 0x47, 0x2e, 0xf3, 0xda, 0x5c, 2); // DEVPROP_TYPE_STRING_LIST
//
// Device interface properties
//
DEFINE_PROPERTYKEY(PKEY_DeviceInterface_FriendlyName, 0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 2); // DEVPROP_TYPE_STRING
DEFINE_PROPERTYKEY(PKEY_DeviceInterface_Enabled, 0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 3); // DEVPROP_TYPE_BOOLEAN
DEFINE_PROPERTYKEY(PKEY_DeviceInterface_ClassGuid, 0x026e516e, 0xb814, 0x414b, 0x83, 0xcd, 0x85, 0x6d, 0x6f, 0xef, 0x48, 0x22, 4); // DEVPROP_TYPE_GUID
//
// Device interface class properties
//
DEFINE_PROPERTYKEY(PKEY_DeviceInterfaceClass_DefaultInterface, 0x14c83a99, 0x0b3f, 0x44b7, 0xbe, 0x4c, 0xa1, 0x78, 0xd3, 0x99, 0x05, 0x64, 2); // DEVPROP_TYPE_STRING
@@ -0,0 +1,38 @@
#ifndef __gInclude__
#define __gInclude__
#if SGI
#undef BEOS
#undef MAC
#undef WINDOWS
//
#define ASIO_BIG_ENDIAN 1
#define ASIO_CPU_MIPS 1
#elif defined(_WIN32) || defined(_WIN64)
#undef BEOS
#undef MAC
#undef SGI
#define WINDOWS 1
#define ASIO_LITTLE_ENDIAN 1
#define ASIO_CPU_X86 1
#elif BEOS
#undef MAC
#undef SGI
#undef WINDOWS
#define ASIO_LITTLE_ENDIAN 1
#define ASIO_CPU_X86 1
//
#else
#define MAC 1
#undef BEOS
#undef WINDOWS
#undef SGI
#define ASIO_BIG_ENDIAN 1
#define ASIO_CPU_PPC 1
#endif
// always
#define NATIVE_INT64 0
#define IEEE754_64FLOAT 1
#endif // __gInclude__
@@ -0,0 +1,37 @@
#include "asiosys.h"
#include "asio.h"
/* Forward Declarations */
#ifndef __ASIODRIVER_FWD_DEFINED__
#define __ASIODRIVER_FWD_DEFINED__
typedef interface IASIO IASIO;
#endif /* __ASIODRIVER_FWD_DEFINED__ */
interface IASIO : public IUnknown
{
virtual ASIOBool init(void *sysHandle) = 0;
virtual void getDriverName(char *name) = 0;
virtual long getDriverVersion() = 0;
virtual void getErrorMessage(char *string) = 0;
virtual ASIOError start() = 0;
virtual ASIOError stop() = 0;
virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels) = 0;
virtual ASIOError getLatencies(long *inputLatency, long *outputLatency) = 0;
virtual ASIOError getBufferSize(long *minSize, long *maxSize,
long *preferredSize, long *granularity) = 0;
virtual ASIOError canSampleRate(ASIOSampleRate sampleRate) = 0;
virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate) = 0;
virtual ASIOError setSampleRate(ASIOSampleRate sampleRate) = 0;
virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources) = 0;
virtual ASIOError setClockSource(long reference) = 0;
virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0;
virtual ASIOError getChannelInfo(ASIOChannelInfo *info) = 0;
virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks) = 0;
virtual ASIOError disposeBuffers() = 0;
virtual ASIOError controlPanel() = 0;
virtual ASIOError future(long selector,void *opt) = 0;
virtual ASIOError outputReady() = 0;
};
@@ -0,0 +1,572 @@
/*
IASIOThiscallResolver.cpp see the comments in iasiothiscallresolver.h for
the top level description - this comment describes the technical details of
the implementation.
The latest version of this file is available from:
http://www.audiomulch.com/~rossb/code/calliasio
please email comments to Ross Bencina <[email protected]>
BACKGROUND
The IASIO interface declared in the Steinberg ASIO 2 SDK declares
functions with no explicit calling convention. This causes MSVC++ to default
to using the thiscall convention, which is a proprietary convention not
implemented by some non-microsoft compilers - notably borland BCC,
C++Builder, and gcc. MSVC++ is the defacto standard compiler used by
Steinberg. As a result of this situation, the ASIO sdk will compile with
any compiler, however attempting to execute the compiled code will cause a
crash due to different default calling conventions on non-Microsoft
compilers.
IASIOThiscallResolver solves the problem by providing an adapter class that
delegates to the IASIO interface using the correct calling convention
(thiscall). Due to the lack of support for thiscall in the Borland and GCC
compilers, the calls have been implemented in assembly language.
A number of macros are defined for thiscall function calls with different
numbers of parameters, with and without return values - it may be possible
to modify the format of these macros to make them work with other inline
assemblers.
THISCALL DEFINITION
A number of definitions of the thiscall calling convention are floating
around the internet. The following definition has been validated against
output from the MSVC++ compiler:
For non-vararg functions, thiscall works as follows: the object (this)
pointer is passed in ECX. All arguments are passed on the stack in
right to left order. The return value is placed in EAX. The callee
clears the passed arguments from the stack.
FINDING FUNCTION POINTERS FROM AN IASIO POINTER
The first field of a COM object is a pointer to its vtble. Thus a pointer
to an object implementing the IASIO interface also points to a pointer to
that object's vtbl. The vtble is a table of function pointers for all of
the virtual functions exposed by the implemented interfaces.
If we consider a variable declared as a pointer to IASO:
IASIO *theAsioDriver
theAsioDriver points to:
object implementing IASIO
{
IASIOvtbl *vtbl
other data
}
in other words, theAsioDriver points to a pointer to an IASIOvtbl
vtbl points to a table of function pointers:
IASIOvtbl ( interface IASIO : public IUnknown )
{
(IUnknown functions)
0 virtual HRESULT STDMETHODCALLTYPE (*QueryInterface)(REFIID riid, void **ppv) = 0;
4 virtual ULONG STDMETHODCALLTYPE (*AddRef)() = 0;
8 virtual ULONG STDMETHODCALLTYPE (*Release)() = 0;
(IASIO functions)
12 virtual ASIOBool (*init)(void *sysHandle) = 0;
16 virtual void (*getDriverName)(char *name) = 0;
20 virtual long (*getDriverVersion)() = 0;
24 virtual void (*getErrorMessage)(char *string) = 0;
28 virtual ASIOError (*start)() = 0;
32 virtual ASIOError (*stop)() = 0;
36 virtual ASIOError (*getChannels)(long *numInputChannels, long *numOutputChannels) = 0;
40 virtual ASIOError (*getLatencies)(long *inputLatency, long *outputLatency) = 0;
44 virtual ASIOError (*getBufferSize)(long *minSize, long *maxSize,
long *preferredSize, long *granularity) = 0;
48 virtual ASIOError (*canSampleRate)(ASIOSampleRate sampleRate) = 0;
52 virtual ASIOError (*getSampleRate)(ASIOSampleRate *sampleRate) = 0;
56 virtual ASIOError (*setSampleRate)(ASIOSampleRate sampleRate) = 0;
60 virtual ASIOError (*getClockSources)(ASIOClockSource *clocks, long *numSources) = 0;
64 virtual ASIOError (*setClockSource)(long reference) = 0;
68 virtual ASIOError (*getSamplePosition)(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0;
72 virtual ASIOError (*getChannelInfo)(ASIOChannelInfo *info) = 0;
76 virtual ASIOError (*createBuffers)(ASIOBufferInfo *bufferInfos, long numChannels,
long bufferSize, ASIOCallbacks *callbacks) = 0;
80 virtual ASIOError (*disposeBuffers)() = 0;
84 virtual ASIOError (*controlPanel)() = 0;
88 virtual ASIOError (*future)(long selector,void *opt) = 0;
92 virtual ASIOError (*outputReady)() = 0;
};
The numbers in the left column show the byte offset of each function ptr
from the beginning of the vtbl. These numbers are used in the code below
to select different functions.
In order to find the address of a particular function, theAsioDriver
must first be dereferenced to find the value of the vtbl pointer:
mov eax, theAsioDriver
mov edx, [theAsioDriver] // edx now points to vtbl[0]
Then an offset must be added to the vtbl pointer to select a
particular function, for example vtbl+44 points to the slot containing
a pointer to the getBufferSize function.
Finally vtbl+x must be dereferenced to obtain the value of the function
pointer stored in that address:
call [edx+44] // call the function pointed to by
// the value in the getBufferSize field of the vtbl
SEE ALSO
Martin Fay's OpenASIO DLL at http://www.martinfay.com solves the same
problem by providing a new COM interface which wraps IASIO with an
interface that uses portable calling conventions. OpenASIO must be compiled
with MSVC, and requires that you ship the OpenASIO DLL with your
application.
ACKNOWLEDGEMENTS
Ross Bencina: worked out the thiscall details above, wrote the original
Borland asm macros, and a patch for asio.cpp (which is no longer needed).
Thanks to Martin Fay for introducing me to the issues discussed here,
and to Rene G. Ceballos for assisting with asm dumps from MSVC++.
Antti Silvast: converted the original calliasio to work with gcc and NASM
by implementing the asm code in a separate file.
Fraser Adams: modified the original calliasio containing the Borland inline
asm to add inline asm for gcc i.e. Intel syntax for Borland and AT&T syntax
for gcc. This seems a neater approach for gcc than to have a separate .asm
file and it means that we only need one version of the thiscall patch.
Fraser Adams: rewrote the original calliasio patch in the form of the
IASIOThiscallResolver class in order to avoid modifications to files from
the Steinberg SDK, which may have had potential licence issues.
Andrew Baldwin: contributed fixes for compatibility problems with more
recent versions of the gcc assembler.
*/
// We only need IASIOThiscallResolver at all if we are on Win32. For other
// platforms we simply bypass the IASIOThiscallResolver definition to allow us
// to be safely #include'd whatever the platform to keep client code portable
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN64)
// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver
// is not used.
#if !defined(_MSC_VER)
#include <new>
#include <assert.h>
// We have a mechanism in iasiothiscallresolver.h to ensure that asio.h is
// #include'd before it in client code, we do NOT want to do this test here.
#define iasiothiscallresolver_sourcefile 1
#include "iasiothiscallresolver.h"
#undef iasiothiscallresolver_sourcefile
// iasiothiscallresolver.h redefines ASIOInit for clients, but we don't want
// this macro defined in this translation unit.
#undef ASIOInit
// theAsioDriver is a global pointer to the current IASIO instance which the
// ASIO SDK uses to perform all actions on the IASIO interface. We substitute
// our own forwarding interface into this pointer.
extern IASIO* theAsioDriver;
// The following macros define the inline assembler for BORLAND first then gcc
#if defined(__BCPLUSPLUS__) || defined(__BORLANDC__)
#define CALL_THISCALL_0( resultName, thisPtr, funcOffset )\
void *this_ = (thisPtr); \
__asm { \
mov ecx, this_ ; \
mov eax, [ecx] ; \
call [eax+funcOffset] ; \
mov resultName, eax ; \
}
#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 )\
void *this_ = (thisPtr); \
__asm { \
mov eax, param1 ; \
push eax ; \
mov ecx, this_ ; \
mov eax, [ecx] ; \
call [eax+funcOffset] ; \
}
#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 )\
void *this_ = (thisPtr); \
__asm { \
mov eax, param1 ; \
push eax ; \
mov ecx, this_ ; \
mov eax, [ecx] ; \
call [eax+funcOffset] ; \
mov resultName, eax ; \
}
#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 )\
void *this_ = (thisPtr); \
void *doubleParamPtr_ (&param1); \
__asm { \
mov eax, doubleParamPtr_ ; \
push [eax+4] ; \
push [eax] ; \
mov ecx, this_ ; \
mov eax, [ecx] ; \
call [eax+funcOffset] ; \
mov resultName, eax ; \
}
#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 )\
void *this_ = (thisPtr); \
__asm { \
mov eax, param2 ; \
push eax ; \
mov eax, param1 ; \
push eax ; \
mov ecx, this_ ; \
mov eax, [ecx] ; \
call [eax+funcOffset] ; \
mov resultName, eax ; \
}
#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\
void *this_ = (thisPtr); \
__asm { \
mov eax, param4 ; \
push eax ; \
mov eax, param3 ; \
push eax ; \
mov eax, param2 ; \
push eax ; \
mov eax, param1 ; \
push eax ; \
mov ecx, this_ ; \
mov eax, [ecx] ; \
call [eax+funcOffset] ; \
mov resultName, eax ; \
}
#elif defined(__GNUC__)
#define CALL_THISCALL_0( resultName, thisPtr, funcOffset ) \
__asm__ __volatile__ ("movl (%1), %%edx\n\t" \
"call *"#funcOffset"(%%edx)\n\t" \
:"=a"(resultName) /* Output Operands */ \
:"c"(thisPtr) /* Input Operands */ \
: "%edx" /* Clobbered Registers */ \
); \
#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 ) \
__asm__ __volatile__ ("pushl %0\n\t" \
"movl (%1), %%edx\n\t" \
"call *"#funcOffset"(%%edx)\n\t" \
: /* Output Operands */ \
:"r"(param1), /* Input Operands */ \
"c"(thisPtr) \
: "%edx" /* Clobbered Registers */ \
); \
#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 ) \
__asm__ __volatile__ ("pushl %1\n\t" \
"movl (%2), %%edx\n\t" \
"call *"#funcOffset"(%%edx)\n\t" \
:"=a"(resultName) /* Output Operands */ \
:"r"(param1), /* Input Operands */ \
"c"(thisPtr) \
: "%edx" /* Clobbered Registers */ \
); \
#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 ) \
do { \
double param1f64 = param1; /* Cast explicitly to double */ \
double *param1f64Ptr = &param1f64; /* Make pointer to address */ \
__asm__ __volatile__ ("pushl 4(%1)\n\t" \
"pushl (%1)\n\t" \
"movl (%2), %%edx\n\t" \
"call *"#funcOffset"(%%edx);\n\t" \
: "=a"(resultName) /* Output Operands */ \
: "r"(param1f64Ptr), /* Input Operands */ \
"c"(thisPtr), \
"m"(*param1f64Ptr) /* Using address */ \
: "%edx" /* Clobbered Registers */ \
); \
} while (0); \
#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 ) \
__asm__ __volatile__ ("pushl %1\n\t" \
"pushl %2\n\t" \
"movl (%3), %%edx\n\t" \
"call *"#funcOffset"(%%edx)\n\t" \
:"=a"(resultName) /* Output Operands */ \
:"r"(param2), /* Input Operands */ \
"r"(param1), \
"c"(thisPtr) \
: "%edx" /* Clobbered Registers */ \
); \
#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\
__asm__ __volatile__ ("pushl %1\n\t" \
"pushl %2\n\t" \
"pushl %3\n\t" \
"pushl %4\n\t" \
"movl (%5), %%edx\n\t" \
"call *"#funcOffset"(%%edx)\n\t" \
:"=a"(resultName) /* Output Operands */ \
:"r"(param4), /* Input Operands */ \
"r"(param3), \
"r"(param2), \
"r"(param1), \
"c"(thisPtr) \
: "%edx" /* Clobbered Registers */ \
); \
#endif
// Our static singleton instance.
IASIOThiscallResolver IASIOThiscallResolver::instance;
// Constructor called to initialize static Singleton instance above. Note that
// it is important not to clear that_ in case it has already been set by the call
// to placement new in ASIOInit().
IASIOThiscallResolver::IASIOThiscallResolver()
{
}
// Constructor called from ASIOInit() below
IASIOThiscallResolver::IASIOThiscallResolver(IASIO* that)
: that_( that )
{
}
// Implement IUnknown methods as assert(false). IASIOThiscallResolver is not
// really a COM object, just a wrapper which will work with the ASIO SDK.
// If you wanted to use ASIO without the SDK you might want to implement COM
// aggregation in these methods.
HRESULT STDMETHODCALLTYPE IASIOThiscallResolver::QueryInterface(REFIID riid, void **ppv)
{
(void)riid; // suppress unused variable warning
assert( false ); // this function should never be called by the ASIO SDK.
*ppv = NULL;
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE IASIOThiscallResolver::AddRef()
{
assert( false ); // this function should never be called by the ASIO SDK.
return 1;
}
ULONG STDMETHODCALLTYPE IASIOThiscallResolver::Release()
{
assert( false ); // this function should never be called by the ASIO SDK.
return 1;
}
// Implement the IASIO interface methods by performing the vptr manipulation
// described above then delegating to the real implementation.
ASIOBool IASIOThiscallResolver::init(void *sysHandle)
{
ASIOBool result;
CALL_THISCALL_1( result, that_, 12, sysHandle );
return result;
}
void IASIOThiscallResolver::getDriverName(char *name)
{
CALL_VOID_THISCALL_1( that_, 16, name );
}
long IASIOThiscallResolver::getDriverVersion()
{
ASIOBool result;
CALL_THISCALL_0( result, that_, 20 );
return result;
}
void IASIOThiscallResolver::getErrorMessage(char *string)
{
CALL_VOID_THISCALL_1( that_, 24, string );
}
ASIOError IASIOThiscallResolver::start()
{
ASIOBool result;
CALL_THISCALL_0( result, that_, 28 );
return result;
}
ASIOError IASIOThiscallResolver::stop()
{
ASIOBool result;
CALL_THISCALL_0( result, that_, 32 );
return result;
}
ASIOError IASIOThiscallResolver::getChannels(long *numInputChannels, long *numOutputChannels)
{
ASIOBool result;
CALL_THISCALL_2( result, that_, 36, numInputChannels, numOutputChannels );
return result;
}
ASIOError IASIOThiscallResolver::getLatencies(long *inputLatency, long *outputLatency)
{
ASIOBool result;
CALL_THISCALL_2( result, that_, 40, inputLatency, outputLatency );
return result;
}
ASIOError IASIOThiscallResolver::getBufferSize(long *minSize, long *maxSize,
long *preferredSize, long *granularity)
{
ASIOBool result;
CALL_THISCALL_4( result, that_, 44, minSize, maxSize, preferredSize, granularity );
return result;
}
ASIOError IASIOThiscallResolver::canSampleRate(ASIOSampleRate sampleRate)
{
ASIOBool result;
CALL_THISCALL_1_DOUBLE( result, that_, 48, sampleRate );
return result;
}
ASIOError IASIOThiscallResolver::getSampleRate(ASIOSampleRate *sampleRate)
{
ASIOBool result;
CALL_THISCALL_1( result, that_, 52, sampleRate );
return result;
}
ASIOError IASIOThiscallResolver::setSampleRate(ASIOSampleRate sampleRate)
{
ASIOBool result;
CALL_THISCALL_1_DOUBLE( result, that_, 56, sampleRate );
return result;
}
ASIOError IASIOThiscallResolver::getClockSources(ASIOClockSource *clocks, long *numSources)
{
ASIOBool result;
CALL_THISCALL_2( result, that_, 60, clocks, numSources );
return result;
}
ASIOError IASIOThiscallResolver::setClockSource(long reference)
{
ASIOBool result;
CALL_THISCALL_1( result, that_, 64, reference );
return result;
}
ASIOError IASIOThiscallResolver::getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
{
ASIOBool result;
CALL_THISCALL_2( result, that_, 68, sPos, tStamp );
return result;
}
ASIOError IASIOThiscallResolver::getChannelInfo(ASIOChannelInfo *info)
{
ASIOBool result;
CALL_THISCALL_1( result, that_, 72, info );
return result;
}
ASIOError IASIOThiscallResolver::createBuffers(ASIOBufferInfo *bufferInfos,
long numChannels, long bufferSize, ASIOCallbacks *callbacks)
{
ASIOBool result;
CALL_THISCALL_4( result, that_, 76, bufferInfos, numChannels, bufferSize, callbacks );
return result;
}
ASIOError IASIOThiscallResolver::disposeBuffers()
{
ASIOBool result;
CALL_THISCALL_0( result, that_, 80 );
return result;
}
ASIOError IASIOThiscallResolver::controlPanel()
{
ASIOBool result;
CALL_THISCALL_0( result, that_, 84 );
return result;
}
ASIOError IASIOThiscallResolver::future(long selector,void *opt)
{
ASIOBool result;
CALL_THISCALL_2( result, that_, 88, selector, opt );
return result;
}
ASIOError IASIOThiscallResolver::outputReady()
{
ASIOBool result;
CALL_THISCALL_0( result, that_, 92 );
return result;
}
// Implement our substitute ASIOInit() method
ASIOError IASIOThiscallResolver::ASIOInit(ASIODriverInfo *info)
{
// To ensure that our instance's vptr is correctly constructed, even if
// ASIOInit is called prior to main(), we explicitly call its constructor
// (potentially over the top of an existing instance). Note that this is
// pretty ugly, and is only safe because IASIOThiscallResolver has no
// destructor and contains no objects with destructors.
new((void*)&instance) IASIOThiscallResolver( theAsioDriver );
// Interpose between ASIO client code and the real driver.
theAsioDriver = &instance;
// Note that we never need to switch theAsioDriver back to point to the
// real driver because theAsioDriver is reset to zero in ASIOExit().
// Delegate to the real ASIOInit
return ::ASIOInit(info);
}
#endif /* !defined(_MSC_VER) */
#endif /* Win32 */
@@ -0,0 +1,202 @@
// ****************************************************************************
//
// Changed: I have modified this file slightly (includes) to work with
// RtAudio. RtAudio.cpp must include this file after asio.h.
//
// File: IASIOThiscallResolver.h
// Description: The IASIOThiscallResolver class implements the IASIO
// interface and acts as a proxy to the real IASIO interface by
// calling through its vptr table using the thiscall calling
// convention. To put it another way, we interpose
// IASIOThiscallResolver between ASIO SDK code and the driver.
// This is necessary because most non-Microsoft compilers don't
// implement the thiscall calling convention used by IASIO.
//
// iasiothiscallresolver.cpp contains the background of this
// problem plus a technical description of the vptr
// manipulations.
//
// In order to use this mechanism one simply has to add
// iasiothiscallresolver.cpp to the list of files to compile
// and #include <iasiothiscallresolver.h>
//
// Note that this #include must come after the other ASIO SDK
// #includes, for example:
//
// #include <windows.h>
// #include <asiosys.h>
// #include <asio.h>
// #include <asiodrivers.h>
// #include <iasiothiscallresolver.h>
//
// Actually the important thing is to #include
// <iasiothiscallresolver.h> after <asio.h>. We have
// incorporated a test to enforce this ordering.
//
// The code transparently takes care of the interposition by
// using macro substitution to intercept calls to ASIOInit()
// and ASIOExit(). We save the original ASIO global
// "theAsioDriver" in our "that" variable, and then set
// "theAsioDriver" to equal our IASIOThiscallResolver instance.
//
// Whilst this method of resolving the thiscall problem requires
// the addition of #include <iasiothiscallresolver.h> to client
// code it has the advantage that it does not break the terms
// of the ASIO licence by publishing it. We are NOT modifying
// any Steinberg code here, we are merely implementing the IASIO
// interface in the same way that we would need to do if we
// wished to provide an open source ASIO driver.
//
// For compilation with MinGW -lole32 needs to be added to the
// linker options. For BORLAND, linking with Import32.lib is
// sufficient.
//
// The dependencies are with: CoInitialize, CoUninitialize,
// CoCreateInstance, CLSIDFromString - used by asiolist.cpp
// and are required on Windows whether ThiscallResolver is used
// or not.
//
// Searching for the above strings in the root library path
// of your compiler should enable the correct libraries to be
// identified if they aren't immediately obvious.
//
// Note that the current implementation of IASIOThiscallResolver
// is not COM compliant - it does not correctly implement the
// IUnknown interface. Implementing it is not necessary because
// it is not called by parts of the ASIO SDK which call through
// theAsioDriver ptr. The IUnknown methods are implemented as
// assert(false) to ensure that the code fails if they are
// ever called.
// Restrictions: None. Public Domain & Open Source distribute freely
// You may use IASIOThiscallResolver commercially as well as
// privately.
// You the user assume the responsibility for the use of the
// files, binary or text, and there is no guarantee or warranty,
// expressed or implied, including but not limited to the
// implied warranties of merchantability and fitness for a
// particular purpose. You assume all responsibility and agree
// to hold no entity, copyright holder or distributors liable
// for any loss of data or inaccurate representations of data
// as a result of using IASIOThiscallResolver.
// Version: 1.4 Added separate macro CALL_THISCALL_1_DOUBLE from
// Andrew Baldwin, and volatile for whole gcc asm blocks,
// both for compatibility with newer gcc versions. Cleaned up
// Borland asm to use one less register.
// 1.3 Switched to including assert.h for better compatibility.
// Wrapped entire .h and .cpp contents with a check for
// _MSC_VER to provide better compatibility with MS compilers.
// Changed Singleton implementation to use static instance
// instead of freestore allocated instance. Removed ASIOExit
// macro as it is no longer needed.
// 1.2 Removed semicolons from ASIOInit and ASIOExit macros to
// allow them to be embedded in expressions (if statements).
// Cleaned up some comments. Removed combase.c dependency (it
// doesn't compile with BCB anyway) by stubbing IUnknown.
// 1.1 Incorporated comments from Ross Bencina including things
// such as changing name from ThiscallResolver to
// IASIOThiscallResolver, tidying up the constructor, fixing
// a bug in IASIOThiscallResolver::ASIOExit() and improving
// portability through the use of conditional compilation
// 1.0 Initial working version.
// Created: 6/09/2003
// Authors: Fraser Adams
// Ross Bencina
// Rene G. Ceballos
// Martin Fay
// Antti Silvast
// Andrew Baldwin
//
// ****************************************************************************
#ifndef included_iasiothiscallresolver_h
#define included_iasiothiscallresolver_h
// We only need IASIOThiscallResolver at all if we are on Win32. For other
// platforms we simply bypass the IASIOThiscallResolver definition to allow us
// to be safely #include'd whatever the platform to keep client code portable
//#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN64)
// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver
// is not used.
#if !defined(_MSC_VER)
// The following is in order to ensure that this header is only included after
// the other ASIO headers (except for the case of iasiothiscallresolver.cpp).
// We need to do this because IASIOThiscallResolver works by eclipsing the
// original definition of ASIOInit() with a macro (see below).
#if !defined(iasiothiscallresolver_sourcefile)
#if !defined(__ASIO_H)
#error iasiothiscallresolver.h must be included AFTER asio.h
#endif
#endif
#include <windows.h>
#include "iasiodrv.h" /* From ASIO SDK */
class IASIOThiscallResolver : public IASIO {
private:
IASIO* that_; // Points to the real IASIO
static IASIOThiscallResolver instance; // Singleton instance
// Constructors - declared private so construction is limited to
// our Singleton instance
IASIOThiscallResolver();
IASIOThiscallResolver(IASIO* that);
public:
// Methods from the IUnknown interface. We don't fully implement IUnknown
// because the ASIO SDK never calls these methods through theAsioDriver ptr.
// These methods are implemented as assert(false).
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv);
virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
// Methods from the IASIO interface, implemented as forwarning calls to that.
virtual ASIOBool init(void *sysHandle);
virtual void getDriverName(char *name);
virtual long getDriverVersion();
virtual void getErrorMessage(char *string);
virtual ASIOError start();
virtual ASIOError stop();
virtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels);
virtual ASIOError getLatencies(long *inputLatency, long *outputLatency);
virtual ASIOError getBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);
virtual ASIOError canSampleRate(ASIOSampleRate sampleRate);
virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate);
virtual ASIOError setSampleRate(ASIOSampleRate sampleRate);
virtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources);
virtual ASIOError setClockSource(long reference);
virtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp);
virtual ASIOError getChannelInfo(ASIOChannelInfo *info);
virtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels, long bufferSize, ASIOCallbacks *callbacks);
virtual ASIOError disposeBuffers();
virtual ASIOError controlPanel();
virtual ASIOError future(long selector,void *opt);
virtual ASIOError outputReady();
// Class method, see ASIOInit() macro below.
static ASIOError ASIOInit(ASIODriverInfo *info); // Delegates to ::ASIOInit
};
// Replace calls to ASIOInit with our interposing version.
// This macro enables us to perform thiscall resolution simply by #including
// <iasiothiscallresolver.h> after the asio #includes (this file _must_ be
// included _after_ the asio #includes)
#define ASIOInit(name) IASIOThiscallResolver::ASIOInit((name))
#endif /* !defined(_MSC_VER) */
#endif /* Win32 */
#endif /* included_iasiothiscallresolver_h */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,54 @@
RtAudio - a set of C++ classes which provide a common API for realtime audio input/output across Linux (native ALSA, JACK, PulseAudio, and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound, ASIO and WASAPI) operating systems.
By Gary P. Scavone, 2001-2021.
To configure and compile (on Unix systems and MinGW):
1. Unpack the RtAudio distribution (tar -xzf rtaudio-x.x.tar.gz).
2. From within the directory containing this file, run configure:
./configure
If you checked out the code from git, just run "autogen.sh".
3. Typing "make" will compile static and shared libraries, as well as the example programs in the "tests/" directory.
A few options can be passed to configure (or the autogen.sh script), including:
--enable-debug = enable various debug output
--with-alsa = choose native ALSA API support (linux only)
--with-pulse = choose native PulseAudio API support (linux only)
--with-oss = choose OSS API support (unixes)
--with-jack = choose JACK server support (linux or Macintosh OS-X)
--with-core = choose CoreAudio API support (Macintosh OS-X only)
--with-asio = choose ASIO API support (windows only)
--with-wasapi = choose Windows Audio System API support (windows only)
--with-ds = choose DirectSound API support (windows only)
Typing "./configure --help" will display all the available options. Note that you can provide more than one "--with-" flag to the configure script to enable multiple API support.
If you wish to use a different compiler than that selected by configure, specify that compiler in the command line (e.g. to use CC):
./configure CXX=CC
CMAKE USAGE:
CMake support is provided via the CMakeLists.txt files. Assuming you have CMake installed on your system, a typical usage would involve the following steps (from within the parent distribution directory):
mkdir _build_
cd _build_
cmake <path to CMakeLists.txt usually two dots> <options> e.g. cmake .. -DAUDIO_WINDOWS_WASAPI=ON
WINDOWS:
All Windows audio APIs in RtAudio compile with either the MinGW compiler (tested with latest tdm64-gcc-4.8.1) or MS Visual Studio.
Visual C++ 6.0 project files (very old) are included for the test programs in the /tests/Windows/ directory. These projects compile API support for ASIO, WASAPI and DirectSound.
LINUX OSS:
The OSS API support in RtAudio has not been tested for many years. I'm not even sure there are OSS drivers supporting recent linux kernels. In all likelihood, the OSS API code in RtAudio will disappear within the next year or two (if you don't want this to happen, let me know).
@@ -0,0 +1,951 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
#
# DESCRIPTION
#
# Check for baseline language coverage in the compiler for the specified
# version of the C++ standard. If necessary, add switches to CXX and
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
# or '14' (for the C++14 standard).
#
# The second argument, if specified, indicates whether you insist on an
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
# -std=c++11). If neither is specified, you get whatever works, with
# preference for an extended mode.
#
# The third argument, if specified 'mandatory' or if left unspecified,
# indicates that baseline support for the specified C++ standard is
# required and that the macro should error out if no mode with that
# support is found. If specified 'optional', then configuration proceeds
# regardless, after defining HAVE_CXX${VERSION} if and only if a
# supporting mode is found.
#
# LICENSE
#
# Copyright (c) 2008 Benjamin Kosnik <[email protected]>
# Copyright (c) 2012 Zack Weinberg <[email protected]>
# Copyright (c) 2013 Roy Stogner <[email protected]>
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <[email protected]>
# Copyright (c) 2015 Paul Norman <[email protected]>
# Copyright (c) 2015 Moritz Klammler <[email protected]>
# Copyright (c) 2016, 2018 Krzesimir Nowak <[email protected]>
# Copyright (c) 2019 Enji Cooper <[email protected]>
#
# 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 11
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
dnl (serial version number 13).
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
[$1], [14], [ax_cxx_compile_alternatives="14 1y"],
[$1], [17], [ax_cxx_compile_alternatives="17 1z"],
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
m4_if([$2], [], [],
[$2], [ext], [],
[$2], [noext], [],
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
[$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
[$3], [optional], [ax_cxx_compile_cxx$1_required=false],
[m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
AC_LANG_PUSH([C++])dnl
ac_success=no
m4_if([$2], [noext], [], [dnl
if test x$ac_success = xno; then
for alternative in ${ax_cxx_compile_alternatives}; do
switch="-std=gnu++${alternative}"
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
$cachevar,
[ac_save_CXX="$CXX"
CXX="$CXX $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXX="$ac_save_CXX"])
if eval test x\$$cachevar = xyes; then
CXX="$CXX $switch"
if test -n "$CXXCPP" ; then
CXXCPP="$CXXCPP $switch"
fi
ac_success=yes
break
fi
done
fi])
m4_if([$2], [ext], [], [dnl
if test x$ac_success = xno; then
dnl HP's aCC needs +std=c++11 according to:
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
dnl Cray's crayCC needs "-h std=c++11"
for alternative in ${ax_cxx_compile_alternatives}; do
for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
$cachevar,
[ac_save_CXX="$CXX"
CXX="$CXX $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXX="$ac_save_CXX"])
if eval test x\$$cachevar = xyes; then
CXX="$CXX $switch"
if test -n "$CXXCPP" ; then
CXXCPP="$CXXCPP $switch"
fi
ac_success=yes
break
fi
done
if test x$ac_success = xyes; then
break
fi
done
fi])
AC_LANG_POP([C++])
if test x$ax_cxx_compile_cxx$1_required = xtrue; then
if test x$ac_success = xno; then
AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
fi
fi
if test x$ac_success = xno; then
HAVE_CXX$1=0
AC_MSG_NOTICE([No compiler with C++$1 support was found])
else
HAVE_CXX$1=1
AC_DEFINE(HAVE_CXX$1,1,
[define if the compiler supports basic C++$1 syntax])
fi
AC_SUBST(HAVE_CXX$1)
])
dnl Test body for checking C++11 support
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
)
dnl Test body for checking C++14 support
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
)
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
)
dnl Tests for new features in C++11
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
// If the compiler admits that it is not ready for C++11, why torture it?
// Hopefully, this will speed up the test.
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201103L
#error "This is not a C++11 compiler"
#else
namespace cxx11
{
namespace test_static_assert
{
template <typename T>
struct check
{
static_assert(sizeof(int) <= sizeof(T), "not big enough");
};
}
namespace test_final_override
{
struct Base
{
virtual ~Base() {}
virtual void f() {}
};
struct Derived : public Base
{
virtual ~Derived() override {}
virtual void f() override {}
};
}
namespace test_double_right_angle_brackets
{
template < typename T >
struct check {};
typedef check<void> single_type;
typedef check<check<void>> double_type;
typedef check<check<check<void>>> triple_type;
typedef check<check<check<check<void>>>> quadruple_type;
}
namespace test_decltype
{
int
f()
{
int a = 1;
decltype(a) b = 2;
return a + b;
}
}
namespace test_type_deduction
{
template < typename T1, typename T2 >
struct is_same
{
static const bool value = false;
};
template < typename T >
struct is_same<T, T>
{
static const bool value = true;
};
template < typename T1, typename T2 >
auto
add(T1 a1, T2 a2) -> decltype(a1 + a2)
{
return a1 + a2;
}
int
test(const int c, volatile int v)
{
static_assert(is_same<int, decltype(0)>::value == true, "");
static_assert(is_same<int, decltype(c)>::value == false, "");
static_assert(is_same<int, decltype(v)>::value == false, "");
auto ac = c;
auto av = v;
auto sumi = ac + av + 'x';
auto sumf = ac + av + 1.0;
static_assert(is_same<int, decltype(ac)>::value == true, "");
static_assert(is_same<int, decltype(av)>::value == true, "");
static_assert(is_same<int, decltype(sumi)>::value == true, "");
static_assert(is_same<int, decltype(sumf)>::value == false, "");
static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
return (sumf > 0.0) ? sumi : add(c, v);
}
}
namespace test_noexcept
{
int f() { return 0; }
int g() noexcept { return 0; }
static_assert(noexcept(f()) == false, "");
static_assert(noexcept(g()) == true, "");
}
namespace test_constexpr
{
template < typename CharT >
unsigned long constexpr
strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
{
return *s ? strlen_c_r(s + 1, acc + 1) : acc;
}
template < typename CharT >
unsigned long constexpr
strlen_c(const CharT *const s) noexcept
{
return strlen_c_r(s, 0UL);
}
static_assert(strlen_c("") == 0UL, "");
static_assert(strlen_c("1") == 1UL, "");
static_assert(strlen_c("example") == 7UL, "");
static_assert(strlen_c("another\0example") == 7UL, "");
}
namespace test_rvalue_references
{
template < int N >
struct answer
{
static constexpr int value = N;
};
answer<1> f(int&) { return answer<1>(); }
answer<2> f(const int&) { return answer<2>(); }
answer<3> f(int&&) { return answer<3>(); }
void
test()
{
int i = 0;
const int c = 0;
static_assert(decltype(f(i))::value == 1, "");
static_assert(decltype(f(c))::value == 2, "");
static_assert(decltype(f(0))::value == 3, "");
}
}
namespace test_uniform_initialization
{
struct test
{
static const int zero {};
static const int one {1};
};
static_assert(test::zero == 0, "");
static_assert(test::one == 1, "");
}
namespace test_lambdas
{
void
test1()
{
auto lambda1 = [](){};
auto lambda2 = lambda1;
lambda1();
lambda2();
}
int
test2()
{
auto a = [](int i, int j){ return i + j; }(1, 2);
auto b = []() -> int { return '0'; }();
auto c = [=](){ return a + b; }();
auto d = [&](){ return c; }();
auto e = [a, &b](int x) mutable {
const auto identity = [](int y){ return y; };
for (auto i = 0; i < a; ++i)
a += b--;
return x + identity(a + b);
}(0);
return a + b + c + d + e;
}
int
test3()
{
const auto nullary = [](){ return 0; };
const auto unary = [](int x){ return x; };
using nullary_t = decltype(nullary);
using unary_t = decltype(unary);
const auto higher1st = [](nullary_t f){ return f(); };
const auto higher2nd = [unary](nullary_t f1){
return [unary, f1](unary_t f2){ return f2(unary(f1())); };
};
return higher1st(nullary) + higher2nd(nullary)(unary);
}
}
namespace test_variadic_templates
{
template <int...>
struct sum;
template <int N0, int... N1toN>
struct sum<N0, N1toN...>
{
static constexpr auto value = N0 + sum<N1toN...>::value;
};
template <>
struct sum<>
{
static constexpr auto value = 0;
};
static_assert(sum<>::value == 0, "");
static_assert(sum<1>::value == 1, "");
static_assert(sum<23>::value == 23, "");
static_assert(sum<1, 2>::value == 3, "");
static_assert(sum<5, 5, 11>::value == 21, "");
static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
}
// http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
// Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
// because of this.
namespace test_template_alias_sfinae
{
struct foo {};
template<typename T>
using member = typename T::member_type;
template<typename T>
void func(...) {}
template<typename T>
void func(member<T>*) {}
void test();
void test() { func<foo>(0); }
}
} // namespace cxx11
#endif // __cplusplus >= 201103L
]])
dnl Tests for new features in C++14
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
// If the compiler admits that it is not ready for C++14, why torture it?
// Hopefully, this will speed up the test.
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201402L
#error "This is not a C++14 compiler"
#else
namespace cxx14
{
namespace test_polymorphic_lambdas
{
int
test()
{
const auto lambda = [](auto&&... args){
const auto istiny = [](auto x){
return (sizeof(x) == 1UL) ? 1 : 0;
};
const int aretiny[] = { istiny(args)... };
return aretiny[0];
};
return lambda(1, 1L, 1.0f, '1');
}
}
namespace test_binary_literals
{
constexpr auto ivii = 0b0000000000101010;
static_assert(ivii == 42, "wrong value");
}
namespace test_generalized_constexpr
{
template < typename CharT >
constexpr unsigned long
strlen_c(const CharT *const s) noexcept
{
auto length = 0UL;
for (auto p = s; *p; ++p)
++length;
return length;
}
static_assert(strlen_c("") == 0UL, "");
static_assert(strlen_c("x") == 1UL, "");
static_assert(strlen_c("test") == 4UL, "");
static_assert(strlen_c("another\0test") == 7UL, "");
}
namespace test_lambda_init_capture
{
int
test()
{
auto x = 0;
const auto lambda1 = [a = x](int b){ return a + b; };
const auto lambda2 = [a = lambda1(x)](){ return a; };
return lambda2();
}
}
namespace test_digit_separators
{
constexpr auto ten_million = 100'000'000;
static_assert(ten_million == 100000000, "");
}
namespace test_return_type_deduction
{
auto f(int& x) { return x; }
decltype(auto) g(int& x) { return x; }
template < typename T1, typename T2 >
struct is_same
{
static constexpr auto value = false;
};
template < typename T >
struct is_same<T, T>
{
static constexpr auto value = true;
};
int
test()
{
auto x = 0;
static_assert(is_same<int, decltype(f(x))>::value, "");
static_assert(is_same<int&, decltype(g(x))>::value, "");
return x;
}
}
} // namespace cxx14
#endif // __cplusplus >= 201402L
]])
dnl Tests for new features in C++17
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
// If the compiler admits that it is not ready for C++17, why torture it?
// Hopefully, this will speed up the test.
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201703L
#error "This is not a C++17 compiler"
#else
#include <initializer_list>
#include <utility>
#include <type_traits>
namespace cxx17
{
namespace test_constexpr_lambdas
{
constexpr int foo = [](){return 42;}();
}
namespace test::nested_namespace::definitions
{
}
namespace test_fold_expression
{
template<typename... Args>
int multiply(Args... args)
{
return (args * ... * 1);
}
template<typename... Args>
bool all(Args... args)
{
return (args && ...);
}
}
namespace test_extended_static_assert
{
static_assert (true);
}
namespace test_auto_brace_init_list
{
auto foo = {5};
auto bar {5};
static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
static_assert(std::is_same<int, decltype(bar)>::value);
}
namespace test_typename_in_template_template_parameter
{
template<template<typename> typename X> struct D;
}
namespace test_fallthrough_nodiscard_maybe_unused_attributes
{
int f1()
{
return 42;
}
[[nodiscard]] int f2()
{
[[maybe_unused]] auto unused = f1();
switch (f1())
{
case 17:
f1();
[[fallthrough]];
case 42:
f1();
}
return f1();
}
}
namespace test_extended_aggregate_initialization
{
struct base1
{
int b1, b2 = 42;
};
struct base2
{
base2() {
b3 = 42;
}
int b3;
};
struct derived : base1, base2
{
int d;
};
derived d1 {{1, 2}, {}, 4}; // full initialization
derived d2 {{}, {}, 4}; // value-initialized bases
}
namespace test_general_range_based_for_loop
{
struct iter
{
int i;
int& operator* ()
{
return i;
}
const int& operator* () const
{
return i;
}
iter& operator++()
{
++i;
return *this;
}
};
struct sentinel
{
int i;
};
bool operator== (const iter& i, const sentinel& s)
{
return i.i == s.i;
}
bool operator!= (const iter& i, const sentinel& s)
{
return !(i == s);
}
struct range
{
iter begin() const
{
return {0};
}
sentinel end() const
{
return {5};
}
};
void f()
{
range r {};
for (auto i : r)
{
[[maybe_unused]] auto v = i;
}
}
}
namespace test_lambda_capture_asterisk_this_by_value
{
struct t
{
int i;
int foo()
{
return [*this]()
{
return i;
}();
}
};
}
namespace test_enum_class_construction
{
enum class byte : unsigned char
{};
byte foo {42};
}
namespace test_constexpr_if
{
template <bool cond>
int f ()
{
if constexpr(cond)
{
return 13;
}
else
{
return 42;
}
}
}
namespace test_selection_statement_with_initializer
{
int f()
{
return 13;
}
int f2()
{
if (auto i = f(); i > 0)
{
return 3;
}
switch (auto i = f(); i + 4)
{
case 17:
return 2;
default:
return 1;
}
}
}
namespace test_template_argument_deduction_for_class_templates
{
template <typename T1, typename T2>
struct pair
{
pair (T1 p1, T2 p2)
: m1 {p1},
m2 {p2}
{}
T1 m1;
T2 m2;
};
void f()
{
[[maybe_unused]] auto p = pair{13, 42u};
}
}
namespace test_non_type_auto_template_parameters
{
template <auto n>
struct B
{};
B<5> b1;
B<'a'> b2;
}
namespace test_structured_bindings
{
int arr[2] = { 1, 2 };
std::pair<int, int> pr = { 1, 2 };
auto f1() -> int(&)[2]
{
return arr;
}
auto f2() -> std::pair<int, int>&
{
return pr;
}
struct S
{
int x1 : 2;
volatile double y1;
};
S f3()
{
return {};
}
auto [ x1, y1 ] = f1();
auto& [ xr1, yr1 ] = f1();
auto [ x2, y2 ] = f2();
auto& [ xr2, yr2 ] = f2();
const auto [ x3, y3 ] = f3();
}
namespace test_exception_spec_type_system
{
struct Good {};
struct Bad {};
void g1() noexcept;
void g2();
template<typename T>
Bad
f(T*, T*);
template<typename T1, typename T2>
Good
f(T1*, T2*);
static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
}
namespace test_inline_variables
{
template<class T> void f(T)
{}
template<class T> inline T g(T)
{
return T{};
}
template<> inline void f<>(int)
{}
template<> int g<>(int)
{
return 5;
}
}
} // namespace cxx17
#endif // __cplusplus < 201703L
]])
@@ -0,0 +1,136 @@
project('RtAudio', 'cpp',
version: '5.2.0',
default_options: ['warning_level=3',
'c_std=c99',
'cpp_std=c++11',
'default_library=both'])
fs = import('fs')
pkg = import('pkgconfig')
rt_h = fs.read('RtAudio.h').strip().split('\n')
foreach line : rt_h
if line.startswith('#define RTAUDIO_VERSION')
rt_version = line.substring(-6,-1)
endif
endforeach
assert(meson.project_version() == rt_version, 'Meson\'s RtAudio version does not match the version in header file.')
ac_file = fs.read('configure.ac').strip().split('\n')
foreach line : ac_file
if line.startswith('m4_define([lt_current],')
lt_current = line.substring(-2,-1).to_int()
elif line.startswith('m4_define([lt_revision],')
lt_revision = line.substring(-2,-1).to_int()
elif line.startswith('m4_define([lt_age],')
lt_age = line.substring(-2,-1).to_int()
endif
endforeach
so_version = '@0@.@1@.@2@'.format(lt_current - lt_age, lt_age, lt_revision)
src = ['RtAudio.cpp', 'rtaudio_c.cpp']
incdir = include_directories('include')
install_headers('RtAudio.h', 'rtaudio_c.h', subdir: 'rtaudio')
compiler = meson.get_compiler('cpp')
deps = []
defines = ['-DRTAUDIO_EXPORT']
if compiler.has_function('gettimeofday', prefix: '#include <sys/time.h>')
defines += '-DHAVE_GETTIMEOFDAY'
endif
if get_option('debug') == true
defines += '-D__RTAUDIO_DEBUG__'
endif
deps += dependency('threads')
alsa_dep = dependency('alsa', required: get_option('alsa'))
if alsa_dep.found()
defines += '-D__LINUX_ALSA__'
deps += alsa_dep
endif
jack_dep = dependency('jack', required: get_option('jack'))
if jack_dep.found()
defines += '-D__UNIX_JACK__'
deps += jack_dep
endif
if get_option('oss') == true
defines += '-D__LINUX_OSS__'
endif
pulsesimple_dep = dependency('libpulse-simple', required: get_option('pulse'))
if pulsesimple_dep.found()
defines += '-D__LINUX_PULSE__'
deps += pulsesimple_dep
endif
core_dep = dependency('appleframeworks', modules: ['CoreAudio', 'CoreFoundation'], required: get_option('core'))
if core_dep.found()
defines += '-D__MACOSX_CORE__'
deps += core_dep
endif
dsound_dep = compiler.find_library('dsound', required: get_option('dsound'))
if dsound_dep.found()
defines += '-D__WINDOWS_DS__'
deps += dsound_dep
endif
wasapi_found = compiler.check_header('audioclient.h', required: get_option('wasapi'))
if wasapi_found
deps += compiler.find_library('mfplat', required: true)
deps += compiler.find_library('mfuuid', required: true)
deps += compiler.find_library('ksuser', required: true)
deps += compiler.find_library('wmcodecdspuuid', required: true)
defines += '-D__WINDOWS_WASAPI__'
endif
asio_found = compiler.check_header('windows.h', required: get_option('asio'))
if asio_found
src += ['include/asio.cpp',
'include/asiolist.cpp',
'include/asiodrivers.cpp',
'include/iasiothiscallresolver.cpp']
defines += '-D__WINDOWS_ASIO__'
endif
if host_machine.system() == 'windows'
deps += compiler.find_library('ole32', required: true)
deps += compiler.find_library('winmm', required: true)
endif
rtaudio = library('rtaudio', src,
version: so_version,
include_directories: incdir,
cpp_args: defines,
dependencies: deps,
gnu_symbol_visibility: 'hidden',
install: true)
rtaudio_dep = declare_dependency(include_directories : '.',
link_with : rtaudio)
meson.override_dependency('rtaudio', rtaudio_dep)
subdir('tests')
subdir('doc')
pkg.generate(rtaudio,
description: 'RtAudio - a set of C++ classes that provide a common API for realtime audio input/output',
subdirs: 'rtaudio')
summary({'ALSA': alsa_dep.found(),
'OSS': get_option('oss'),
'JACK': jack_dep.found(),
'PulseAudio': pulsesimple_dep.found(),
'CoreAudio': core_dep.found(),
'DirectAudio': dsound_dep.found(),
'WASAPI': wasapi_found,
'ASIO': asio_found}, bool_yn: true, section: 'Audio Backends')
@@ -0,0 +1,13 @@
# Audio Backends
option('jack', type : 'feature', value : 'auto', description: 'Build with JACK Backend')
option('alsa', type : 'feature', value : 'auto', description: 'Build with ALSA Backend')
option('pulse', type : 'feature', value : 'auto', description: 'Build with Pulseaudio Backend')
option('oss', type : 'boolean', value : 'false', description: 'Build with OSS Backend')
option('core', type : 'feature', value : 'auto', description: 'Build with CoreAudio Backend')
option('dsound', type : 'feature', value : 'auto', description: 'Build with DirectSound Backend')
option('asio', type : 'feature', value : 'auto', description: 'Build with ASIO Backend')
option('wasapi', type : 'feature', value : 'auto', description: 'Build with WASAPI Backend')
#
option('docs', type : 'boolean', value : 'false', description: 'Generate API documentation')
option('install_docs', type : 'boolean', value : 'false', description: 'Install API documentation')
@@ -0,0 +1,12 @@
prefix=@prefix@
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include/rtaudio
Name: librtaudio
Description: RtAudio - a set of C++ classes that provide a common API for realtime audio input/output
Version: @PACKAGE_VERSION@
Requires.private: @req@
Libs: -L${libdir} -lrtaudio
Libs.private: -lpthread @req_libs@
Cflags: -pthread -I${includedir} @api@
@@ -0,0 +1,267 @@
#include "rtaudio_c.h"
#include "RtAudio.h"
#include <cstring>
#define MAX_ERROR_MESSAGE_LENGTH 512
struct rtaudio {
RtAudio *audio;
rtaudio_cb_t cb;
void *userdata;
rtaudio_error_t errtype;
char errmsg[MAX_ERROR_MESSAGE_LENGTH];
};
const char *rtaudio_version() { return RTAUDIO_VERSION; }
extern "C" const RtAudio::Api rtaudio_compiled_apis[];
const rtaudio_api_t *rtaudio_compiled_api() {
return (rtaudio_api_t *) &rtaudio_compiled_apis[0];
}
extern "C" const unsigned int rtaudio_num_compiled_apis;
unsigned int rtaudio_get_num_compiled_apis(void) {
return rtaudio_num_compiled_apis;
}
extern "C" const char* rtaudio_api_names[][2];
const char *rtaudio_api_name(rtaudio_api_t api) {
if (api < 0 || api >= RTAUDIO_API_NUM)
return NULL;
return rtaudio_api_names[api][0];
}
const char *rtaudio_api_display_name(rtaudio_api_t api)
{
if (api < 0 || api >= RTAUDIO_API_NUM)
return "Unknown";
return rtaudio_api_names[api][1];
}
rtaudio_api_t rtaudio_compiled_api_by_name(const char *name) {
RtAudio::Api api = RtAudio::UNSPECIFIED;
if (name) {
api = RtAudio::getCompiledApiByName(name);
}
return (rtaudio_api_t)api;
}
const char *rtaudio_error(rtaudio_t audio) {
if (audio->errtype == RTAUDIO_NO_ERROR) {
return NULL;
}
return audio->errmsg;
}
rtaudio_error_t rtaudio_error_type(rtaudio_t audio) {
return audio->errtype;
}
rtaudio_t rtaudio_create(rtaudio_api_t api) {
rtaudio_t audio = new struct rtaudio();
try {
audio->errtype = RTAUDIO_NO_ERROR;
audio->audio = new RtAudio((RtAudio::Api)api);
} catch (RtAudioError &err) {
audio->errtype = (rtaudio_error_t)err.getType();
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
}
return audio;
}
void rtaudio_destroy(rtaudio_t audio) { delete audio->audio; }
rtaudio_api_t rtaudio_current_api(rtaudio_t audio) {
return (rtaudio_api_t)audio->audio->getCurrentApi();
}
int rtaudio_device_count(rtaudio_t audio) {
return audio->audio->getDeviceCount();
}
rtaudio_device_info_t rtaudio_get_device_info(rtaudio_t audio, int i) {
rtaudio_device_info_t result;
std::memset(&result, 0, sizeof(result));
try {
audio->errtype = RTAUDIO_NO_ERROR;;
RtAudio::DeviceInfo info = audio->audio->getDeviceInfo(i);
result.probed = info.probed;
result.output_channels = info.outputChannels;
result.input_channels = info.inputChannels;
result.duplex_channels = info.duplexChannels;
result.is_default_output = info.isDefaultOutput;
result.is_default_input = info.isDefaultInput;
result.native_formats = info.nativeFormats;
result.preferred_sample_rate = info.preferredSampleRate;
strncpy(result.name, info.name.c_str(), sizeof(result.name) - 1);
for (unsigned int j = 0; j < info.sampleRates.size(); j++) {
if (j < sizeof(result.sample_rates) / sizeof(result.sample_rates[0])) {
result.sample_rates[j] = info.sampleRates[j];
}
}
} catch (RtAudioError &err) {
audio->errtype = (rtaudio_error_t)err.getType();
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
}
return result;
}
unsigned int rtaudio_get_default_output_device(rtaudio_t audio) {
return audio->audio->getDefaultOutputDevice();
}
unsigned int rtaudio_get_default_input_device(rtaudio_t audio) {
return audio->audio->getDefaultInputDevice();
}
static int proxy_cb_func(void *out, void *in, unsigned int nframes, double time,
RtAudioStreamStatus status, void *userdata) {
rtaudio_t audio = (rtaudio_t)userdata;
return audio->cb(out, in, nframes, time, (rtaudio_stream_status_t)status,
audio->userdata);
}
int rtaudio_open_stream(rtaudio_t audio,
rtaudio_stream_parameters_t *output_params,
rtaudio_stream_parameters_t *input_params,
rtaudio_format_t format, unsigned int sample_rate,
unsigned int *buffer_frames, rtaudio_cb_t cb,
void *userdata, rtaudio_stream_options_t *options,
rtaudio_error_cb_t /*errcb*/) {
try {
audio->errtype = RTAUDIO_NO_ERROR;;
RtAudio::StreamParameters *in = NULL;
RtAudio::StreamParameters *out = NULL;
RtAudio::StreamOptions *opts = NULL;
RtAudio::StreamParameters inparams;
RtAudio::StreamParameters outparams;
RtAudio::StreamOptions stream_opts;
if (input_params != NULL) {
inparams.deviceId = input_params->device_id;
inparams.nChannels = input_params->num_channels;
inparams.firstChannel = input_params->first_channel;
in = &inparams;
}
if (output_params != NULL) {
outparams.deviceId = output_params->device_id;
outparams.nChannels = output_params->num_channels;
outparams.firstChannel = output_params->first_channel;
out = &outparams;
}
if (options != NULL) {
stream_opts.flags = (RtAudioStreamFlags)options->flags;
stream_opts.numberOfBuffers = options->num_buffers;
stream_opts.priority = options->priority;
if (strlen(options->name) > 0) {
stream_opts.streamName = std::string(options->name);
}
opts = &stream_opts;
}
audio->cb = cb;
audio->userdata = userdata;
audio->audio->openStream(out, in, (RtAudioFormat)format, sample_rate,
buffer_frames, proxy_cb_func, (void *)audio, opts,
NULL);
return 0;
} catch (RtAudioError &err) {
audio->errtype = (rtaudio_error_t)err.getType();
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
return -1;
}
}
void rtaudio_close_stream(rtaudio_t audio) { audio->audio->closeStream(); }
int rtaudio_start_stream(rtaudio_t audio) {
try {
audio->errtype = RTAUDIO_NO_ERROR;;
audio->audio->startStream();
} catch (RtAudioError &err) {
audio->errtype = (rtaudio_error_t)err.getType();
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
}
return 0;
}
int rtaudio_stop_stream(rtaudio_t audio) {
try {
audio->errtype = RTAUDIO_NO_ERROR;;
audio->audio->stopStream();
} catch (RtAudioError &err) {
audio->errtype = (rtaudio_error_t)err.getType();
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
}
return 0;
}
int rtaudio_abort_stream(rtaudio_t audio) {
try {
audio->errtype = RTAUDIO_NO_ERROR;;
audio->audio->abortStream();
} catch (RtAudioError &err) {
audio->errtype = (rtaudio_error_t)err.getType();
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
}
return 0;
}
int rtaudio_is_stream_open(rtaudio_t audio) {
return !!audio->audio->isStreamOpen();
}
int rtaudio_is_stream_running(rtaudio_t audio) {
return !!audio->audio->isStreamRunning();
}
double rtaudio_get_stream_time(rtaudio_t audio) {
try {
audio->errtype = RTAUDIO_NO_ERROR;;
return audio->audio->getStreamTime();
} catch (RtAudioError &err) {
audio->errtype = (rtaudio_error_t)err.getType();
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
return 0;
}
}
void rtaudio_set_stream_time(rtaudio_t audio, double time) {
try {
audio->errtype = RTAUDIO_NO_ERROR;;
audio->audio->setStreamTime(time);
} catch (RtAudioError &err) {
audio->errtype = (rtaudio_error_t)err.getType();
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
}
}
int rtaudio_get_stream_latency(rtaudio_t audio) {
try {
audio->errtype = RTAUDIO_NO_ERROR;
return audio->audio->getStreamLatency();
} catch (RtAudioError &err) {
audio->errtype = (rtaudio_error_t)err.getType();
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
return -1;
}
}
unsigned int rtaudio_get_stream_sample_rate(rtaudio_t audio) {
try {
audio->errtype = RTAUDIO_NO_ERROR;
return audio->audio->getStreamSampleRate();
} catch (RtAudioError &err) {
audio->errtype = (rtaudio_error_t)err.getType();
strncpy(audio->errmsg, err.what(), sizeof(audio->errmsg) - 1);
return -1;
}
}
void rtaudio_show_warnings(rtaudio_t audio, int show) {
audio->audio->showWarnings(!!show);
}
@@ -0,0 +1,309 @@
/************************************************************************/
/*! \defgroup C-interface
@{
\brief C interface to realtime audio i/o C++ classes.
RtAudio offers a C-style interface, principally for use in binding
RtAudio to other programming languages. All structs, enums, and
functions listed here have direct analogs (and simply call to)
items in the C++ RtAudio class and its supporting classes and
types
*/
/************************************************************************/
/*!
\file rtaudio_c.h
*/
#ifndef RTAUDIO_C_H
#define RTAUDIO_C_H
#if defined(RTAUDIO_EXPORT)
#if defined _WIN32 || defined __CYGWIN__
#define RTAUDIOAPI __declspec(dllexport)
#else
#define RTAUDIOAPI __attribute__((visibility("default")))
#endif
#else
#define RTAUDIOAPI //__declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*! \typedef typedef unsigned long rtaudio_format_t;
\brief RtAudio data format type.
- \e RTAUDIO_FORMAT_SINT8: 8-bit signed integer.
- \e RTAUDIO_FORMAT_SINT16: 16-bit signed integer.
- \e RTAUDIO_FORMAT_SINT24: 24-bit signed integer.
- \e RTAUDIO_FORMAT_SINT32: 32-bit signed integer.
- \e RTAUDIO_FORMAT_FLOAT32: Normalized between plus/minus 1.0.
- \e RTAUDIO_FORMAT_FLOAT64: Normalized between plus/minus 1.0.
See \ref RtAudioFormat.
*/
typedef unsigned long rtaudio_format_t;
#define RTAUDIO_FORMAT_SINT8 0x01
#define RTAUDIO_FORMAT_SINT16 0x02
#define RTAUDIO_FORMAT_SINT24 0x04
#define RTAUDIO_FORMAT_SINT32 0x08
#define RTAUDIO_FORMAT_FLOAT32 0x10
#define RTAUDIO_FORMAT_FLOAT64 0x20
/*! \typedef typedef unsigned long rtaudio_stream_flags_t;
\brief RtAudio stream option flags.
The following flags can be OR'ed together to allow a client to
make changes to the default stream behavior:
- \e RTAUDIO_FLAGS_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved).
- \e RTAUDIO_FLAGS_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency.
- \e RTAUDIO_FLAGS_HOG_DEVICE: Attempt grab device for exclusive use.
- \e RTAUDIO_FLAGS_ALSA_USE_DEFAULT: Use the "default" PCM device (ALSA only).
- \e RTAUDIO_FLAGS_JACK_DONT_CONNECT: Do not automatically connect ports (JACK only).
See \ref RtAudioStreamFlags.
*/
typedef unsigned int rtaudio_stream_flags_t;
#define RTAUDIO_FLAGS_NONINTERLEAVED 0x1
#define RTAUDIO_FLAGS_MINIMIZE_LATENCY 0x2
#define RTAUDIO_FLAGS_HOG_DEVICE 0x4
#define RTAUDIO_FLAGS_SCHEDULE_REALTIME 0x8
#define RTAUDIO_FLAGS_ALSA_USE_DEFAULT 0x10
#define RTAUDIO_FLAGS_JACK_DONT_CONNECT 0x20
/*! \typedef typedef unsigned long rtaudio_stream_status_t;
\brief RtAudio stream status (over- or underflow) flags.
Notification of a stream over- or underflow is indicated by a
non-zero stream \c status argument in the RtAudioCallback function.
The stream status can be one of the following two options,
depending on whether the stream is open for output and/or input:
- \e RTAUDIO_STATUS_INPUT_OVERFLOW: Input data was discarded because of an overflow condition at the driver.
- \e RTAUDIO_STATUS_OUTPUT_UNDERFLOW: The output buffer ran low, likely producing a break in the output sound.
See \ref RtAudioStreamStatus.
*/
typedef unsigned int rtaudio_stream_status_t;
#define RTAUDIO_STATUS_INPUT_OVERFLOW 0x1
#define RTAUDIO_STATUS_OUTPUT_UNDERFLOW 0x2
//! RtAudio callback function prototype.
/*!
All RtAudio clients must create a function of this type to read
and/or write data from/to the audio stream. When the underlying
audio system is ready for new input or output data, this function
will be invoked.
See \ref RtAudioCallback.
*/
typedef int (*rtaudio_cb_t)(void *out, void *in, unsigned int nFrames,
double stream_time, rtaudio_stream_status_t status,
void *userdata);
/*! \brief Error codes for RtAudio.
See \ref RtAudioError.
*/
typedef enum rtaudio_error {
RTAUDIO_NO_ERROR = -1, /*!< No error. */
RTAUDIO_ERROR_WARNING, /*!< A non-critical error. */
RTAUDIO_ERROR_DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */
RTAUDIO_ERROR_UNSPECIFIED, /*!< The default, unspecified error type. */
RTAUDIO_ERROR_NO_DEVICES_FOUND, /*!< No devices found on system. */
RTAUDIO_ERROR_INVALID_DEVICE, /*!< An invalid device ID was specified. */
RTAUDIO_ERROR_MEMORY_ERROR, /*!< An error occurred during memory allocation. */
RTAUDIO_ERROR_INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */
RTAUDIO_ERROR_INVALID_USE, /*!< The function was called incorrectly. */
RTAUDIO_ERROR_DRIVER_ERROR, /*!< A system driver error occurred. */
RTAUDIO_ERROR_SYSTEM_ERROR, /*!< A system error occurred. */
RTAUDIO_ERROR_THREAD_ERROR, /*!< A thread error occurred. */
} rtaudio_error_t;
//! RtAudio error callback function prototype.
/*!
\param err Type of error.
\param msg Error description.
See \ref RtAudioErrorCallback.
*/
typedef void (*rtaudio_error_cb_t)(rtaudio_error_t err, const char *msg);
//! Audio API specifier. See \ref RtAudio::Api.
typedef enum rtaudio_api {
RTAUDIO_API_UNSPECIFIED, /*!< Search for a working compiled API. */
RTAUDIO_API_LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */
RTAUDIO_API_LINUX_PULSE, /*!< The Linux PulseAudio API. */
RTAUDIO_API_LINUX_OSS, /*!< The Linux Open Sound System API. */
RTAUDIO_API_UNIX_JACK, /*!< The Jack Low-Latency Audio Server API. */
RTAUDIO_API_MACOSX_CORE, /*!< Macintosh OS-X Core Audio API. */
RTAUDIO_API_WINDOWS_WASAPI, /*!< The Microsoft WASAPI API. */
RTAUDIO_API_WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O API. */
RTAUDIO_API_WINDOWS_DS, /*!< The Microsoft DirectSound API. */
RTAUDIO_API_DUMMY, /*!< A compilable but non-functional API. */
RTAUDIO_API_NUM, /*!< Number of values in this enum. */
} rtaudio_api_t;
#define NUM_SAMPLE_RATES 16
#define MAX_NAME_LENGTH 512
//! The public device information structure for returning queried values.
//! See \ref RtAudio::DeviceInfo.
typedef struct rtaudio_device_info {
int probed;
unsigned int output_channels;
unsigned int input_channels;
unsigned int duplex_channels;
int is_default_output;
int is_default_input;
rtaudio_format_t native_formats;
unsigned int preferred_sample_rate;
int sample_rates[NUM_SAMPLE_RATES];
char name[MAX_NAME_LENGTH];
} rtaudio_device_info_t;
//! The structure for specifying input or output stream parameters.
//! See \ref RtAudio::StreamParameters.
typedef struct rtaudio_stream_parameters {
unsigned int device_id;
unsigned int num_channels;
unsigned int first_channel;
} rtaudio_stream_parameters_t;
//! The structure for specifying stream options.
//! See \ref RtAudio::StreamOptions.
typedef struct rtaudio_stream_options {
rtaudio_stream_flags_t flags;
unsigned int num_buffers;
int priority;
char name[MAX_NAME_LENGTH];
} rtaudio_stream_options_t;
typedef struct rtaudio *rtaudio_t;
//! Determine the current RtAudio version. See \ref RtAudio::getVersion().
RTAUDIOAPI const char *rtaudio_version(void);
//! Determine the number of available compiled audio APIs, the length
//! of the array returned by rtaudio_compiled_api(). See \ref
//! RtAudio::getCompiledApi().
RTAUDIOAPI unsigned int rtaudio_get_num_compiled_apis(void);
//! Return an array of rtaudio_api_t compiled into this instance of
//! RtAudio. This array is static (do not free it) and has the length
//! returned by rtaudio_get_num_compiled_apis(). See \ref
//! RtAudio::getCompiledApi().
RTAUDIOAPI const rtaudio_api_t *rtaudio_compiled_api(void);
//! Return the name of a specified rtaudio_api_t. This string can be
//! used to look up an API by rtaudio_compiled_api_by_name(). See
//! \ref RtAudio::getApiName().
RTAUDIOAPI const char *rtaudio_api_name(rtaudio_api_t api);
//! Return the display name of a specified rtaudio_api_t. See \ref
//! RtAudio::getApiDisplayName().
RTAUDIOAPI const char *rtaudio_api_display_name(rtaudio_api_t api);
//! Return the rtaudio_api_t having the given name. See \ref
//! RtAudio::getCompiledApiByName().
RTAUDIOAPI rtaudio_api_t rtaudio_compiled_api_by_name(const char *name);
RTAUDIOAPI const char *rtaudio_error(rtaudio_t audio);
RTAUDIOAPI rtaudio_error_t rtaudio_error_type(rtaudio_t audio);
//! Create an instance of struct rtaudio.
RTAUDIOAPI rtaudio_t rtaudio_create(rtaudio_api_t api);
//! Free an instance of struct rtaudio.
RTAUDIOAPI void rtaudio_destroy(rtaudio_t audio);
//! Returns the audio API specifier for the current instance of
//! RtAudio. See RtAudio::getCurrentApi().
RTAUDIOAPI rtaudio_api_t rtaudio_current_api(rtaudio_t audio);
//! Queries for the number of audio devices available. See \ref
//! RtAudio::getDeviceCount().
RTAUDIOAPI int rtaudio_device_count(rtaudio_t audio);
//! Return a struct rtaudio_device_info for a specified device number.
//! See \ref RtAudio::getDeviceInfo().
RTAUDIOAPI rtaudio_device_info_t rtaudio_get_device_info(rtaudio_t audio,
int i);
//! Returns the index of the default output device. See \ref
//! RtAudio::getDefaultOutputDevice().
RTAUDIOAPI unsigned int rtaudio_get_default_output_device(rtaudio_t audio);
//! Returns the index of the default input device. See \ref
//! RtAudio::getDefaultInputDevice().
RTAUDIOAPI unsigned int rtaudio_get_default_input_device(rtaudio_t audio);
//! Opens a stream with the specified parameters. See \ref RtAudio::openStream().
//! \return an \ref rtaudio_error.
RTAUDIOAPI int
rtaudio_open_stream(rtaudio_t audio, rtaudio_stream_parameters_t *output_params,
rtaudio_stream_parameters_t *input_params,
rtaudio_format_t format, unsigned int sample_rate,
unsigned int *buffer_frames, rtaudio_cb_t cb,
void *userdata, rtaudio_stream_options_t *options,
rtaudio_error_cb_t errcb);
//! Closes a stream and frees any associated stream memory. See \ref RtAudio::closeStream().
RTAUDIOAPI void rtaudio_close_stream(rtaudio_t audio);
//! Starts a stream. See \ref RtAudio::startStream().
RTAUDIOAPI int rtaudio_start_stream(rtaudio_t audio);
//! Stop a stream, allowing any samples remaining in the output queue
//! to be played. See \ref RtAudio::stopStream().
RTAUDIOAPI int rtaudio_stop_stream(rtaudio_t audio);
//! Stop a stream, discarding any samples remaining in the
//! input/output queue. See \ref RtAudio::abortStream().
RTAUDIOAPI int rtaudio_abort_stream(rtaudio_t audio);
//! Returns 1 if a stream is open and false if not. See \ref RtAudio::isStreamOpen().
RTAUDIOAPI int rtaudio_is_stream_open(rtaudio_t audio);
//! Returns 1 if a stream is running and false if it is stopped or not
//! open. See \ref RtAudio::isStreamRunning().
RTAUDIOAPI int rtaudio_is_stream_running(rtaudio_t audio);
//! Returns the number of elapsed seconds since the stream was
//! started. See \ref RtAudio::getStreamTime().
RTAUDIOAPI double rtaudio_get_stream_time(rtaudio_t audio);
//! Set the stream time to a time in seconds greater than or equal to
//! 0.0. See \ref RtAudio::setStreamTime().
RTAUDIOAPI void rtaudio_set_stream_time(rtaudio_t audio, double time);
//! Returns the internal stream latency in sample frames. See \ref
//! RtAudio::getStreamLatency().
RTAUDIOAPI int rtaudio_get_stream_latency(rtaudio_t audio);
//! Returns actual sample rate in use by the stream. See \ref
//! RtAudio::getStreamSampleRate().
RTAUDIOAPI unsigned int rtaudio_get_stream_sample_rate(rtaudio_t audio);
//! Specify whether warning messages should be printed to stderr. See
//! \ref RtAudio::showWarnings().
RTAUDIOAPI void rtaudio_show_warnings(rtaudio_t audio, int show);
#ifdef __cplusplus
}
#endif
#endif /* RTAUDIO_C_H */
/*! }@ */
@@ -0,0 +1,32 @@
include_directories(..)
if (WIN32)
include_directories(../include)
endif (WIN32)
list(GET LIB_TARGETS 0 LIBRTAUDIO)
add_executable(audioprobe audioprobe.cpp)
target_link_libraries(audioprobe ${LIBRTAUDIO} ${LINKLIBS})
add_executable(playsaw playsaw.cpp)
target_link_libraries(playsaw ${LIBRTAUDIO} ${LINKLIBS})
add_executable(playraw playraw.cpp)
target_link_libraries(playraw ${LIBRTAUDIO} ${LINKLIBS})
add_executable(record record.cpp)
target_link_libraries(record ${LIBRTAUDIO} ${LINKLIBS})
add_executable(duplex duplex.cpp)
target_link_libraries(duplex ${LIBRTAUDIO} ${LINKLIBS})
add_executable(apinames apinames.cpp)
target_link_libraries(apinames ${LIBRTAUDIO} ${LINKLIBS})
add_executable(testall testall.cpp)
target_link_libraries(testall ${LIBRTAUDIO} ${LINKLIBS})
add_executable(teststops teststops.cpp)
target_link_libraries(teststops ${LIBRTAUDIO} ${LINKLIBS})
add_test(NAME apinames COMMAND apinames)
@@ -0,0 +1,32 @@
noinst_PROGRAMS = audioprobe playsaw playraw record duplex apinames testall teststops
AM_CXXFLAGS = -Wall -I$(top_srcdir)
audioprobe_SOURCES = audioprobe.cpp
audioprobe_LDADD = $(top_builddir)/librtaudio.la
playsaw_SOURCES = playsaw.cpp
playsaw_LDADD = $(top_builddir)/librtaudio.la
playraw_SOURCES = playraw.cpp
playraw_LDADD = $(top_builddir)/librtaudio.la
record_SOURCES = record.cpp
record_LDADD = $(top_builddir)/librtaudio.la
duplex_SOURCES = duplex.cpp
duplex_LDADD = $(top_builddir)/librtaudio.la
apinames_SOURCES = apinames.cpp
apinames_LDADD = $(top_builddir)/librtaudio.la
testall_SOURCES = testall.cpp
testall_LDADD = $(top_builddir)/librtaudio.la
teststops_SOURCES = teststops.cpp
teststops_LDADD = $(top_builddir)/librtaudio.la
EXTRA_DIST = Windows CMakeLists.txt
TESTS = apinames
@@ -0,0 +1,158 @@
# Microsoft Developer Studio Project File - Name="audioprobe" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=audioprobe - Win32 Debug
!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 "audioprobe.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 "audioprobe.mak" CFG="audioprobe - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "audioprobe - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "audioprobe - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "audioprobe - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "audioprobe___Win32_Release"
# PROP BASE Intermediate_Dir "audioprobe___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../include" /D "NDEBUG" /D "__WINDOWS_DS__" /D "__WINDOWS_ASIO__" /D "__WINDOWS_WASAPI__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# 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 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 /subsystem:console /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 dsound.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "audioprobe - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "audioprobe___Win32_Debug"
# PROP BASE Intermediate_Dir "audioprobe___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../include" /D "_DEBUG" /D "__WINDOWS_DS__" /D "__WINDOWS_ASIO__" /D "__WINDOWS_WASAPI__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# 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 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 /subsystem:console /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 dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "audioprobe - Win32 Release"
# Name "audioprobe - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\include\asio.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrivers.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\asiolist.cpp
# End Source File
# Begin Source File
SOURCE=..\audioprobe.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiothiscallresolver.cpp
# End Source File
# Begin Source File
SOURCE=..\..\RtAudio.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\include\asio.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrivers.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrvr.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiolist.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiosys.h
# End Source File
# Begin Source File
SOURCE=..\..\include\ginclude.h
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiodrv.h
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiothiscallresolver.h
# End Source File
# Begin Source File
SOURCE=..\..\RtAudio.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project
@@ -0,0 +1,158 @@
# Microsoft Developer Studio Project File - Name="duplex" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=duplex - Win32 Debug
!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 "duplex.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 "duplex.mak" CFG="duplex - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "duplex - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "duplex - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "duplex - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "duplex___Win32_Release"
# PROP BASE Intermediate_Dir "duplex___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../include" /D "NDEBUG" /D "__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_WASAPI__" /YX /FD /c
# 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 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 /subsystem:console /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 dsound.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "duplex - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "duplex___Win32_Debug"
# PROP BASE Intermediate_Dir "duplex___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../include" /D "_DEBUG" /D "__WINDOWS_ASIO__.__WINDOWS_DS__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /GZ /c
# 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 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 /subsystem:console /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 dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "duplex - Win32 Release"
# Name "duplex - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\include\asio.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrivers.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\asiolist.cpp
# End Source File
# Begin Source File
SOURCE=..\duplex.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiothiscallresolver.cpp
# End Source File
# Begin Source File
SOURCE=..\..\RtAudio.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\include\asio.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrivers.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrvr.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiolist.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiosys.h
# End Source File
# Begin Source File
SOURCE=..\..\include\ginclude.h
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiodrv.h
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiothiscallresolver.h
# End Source File
# Begin Source File
SOURCE=..\..\RtAudio.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project
@@ -0,0 +1,158 @@
# Microsoft Developer Studio Project File - Name="playraw" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=playraw - Win32 Debug
!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 "playraw.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 "playraw.mak" CFG="playraw - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "playraw - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "playraw - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "playraw - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "playraw___Win32_Release"
# PROP BASE Intermediate_Dir "playraw___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /c
# 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 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 /subsystem:console /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 dsound.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "playraw - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "playraw___Win32_Debug"
# PROP BASE Intermediate_Dir "playraw___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /GZ /c
# 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 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 /subsystem:console /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 dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "playraw - Win32 Release"
# Name "playraw - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\include\asio.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrivers.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\asiolist.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiothiscallresolver.cpp
# End Source File
# Begin Source File
SOURCE=..\playraw.cpp
# End Source File
# Begin Source File
SOURCE=..\..\RtAudio.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\include\asio.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrivers.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrvr.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiolist.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiosys.h
# End Source File
# Begin Source File
SOURCE=..\..\include\ginclude.h
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiodrv.h
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiothiscallresolver.h
# End Source File
# Begin Source File
SOURCE=..\..\RtAudio.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project
@@ -0,0 +1,158 @@
# Microsoft Developer Studio Project File - Name="playsaw" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=playsaw - Win32 Debug
!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 "playsaw.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 "playsaw.mak" CFG="playsaw - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "playsaw - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "playsaw - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "playsaw - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "playsaw___Win32_Release"
# PROP BASE Intermediate_Dir "playsaw___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /c
# 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 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 /subsystem:console /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 dsound.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "playsaw - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "playsaw___Win32_Debug"
# PROP BASE Intermediate_Dir "playsaw___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /GZ /c
# 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 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 /subsystem:console /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 dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "playsaw - Win32 Release"
# Name "playsaw - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\include\asio.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrivers.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\asiolist.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiothiscallresolver.cpp
# End Source File
# Begin Source File
SOURCE=..\playsaw.cpp
# End Source File
# Begin Source File
SOURCE=..\..\RtAudio.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\include\asio.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrivers.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrvr.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiolist.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiosys.h
# End Source File
# Begin Source File
SOURCE=..\..\include\ginclude.h
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiodrv.h
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiothiscallresolver.h
# End Source File
# Begin Source File
SOURCE=..\..\RtAudio.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project
@@ -0,0 +1,158 @@
# Microsoft Developer Studio Project File - Name="record" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=record - Win32 Debug
!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 "record.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 "record.mak" CFG="record - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "record - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "record - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "record - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "record___Win32_Release"
# PROP BASE Intermediate_Dir "record___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /c
# 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 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 /subsystem:console /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 dsound.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "record - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "record___Win32_Debug"
# PROP BASE Intermediate_Dir "record___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /GZ /c
# 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 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 /subsystem:console /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 dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "record - Win32 Release"
# Name "record - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\include\asio.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrivers.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\asiolist.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiothiscallresolver.cpp
# End Source File
# Begin Source File
SOURCE=..\record.cpp
# End Source File
# Begin Source File
SOURCE=..\..\RtAudio.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\include\asio.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrivers.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrvr.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiolist.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiosys.h
# End Source File
# Begin Source File
SOURCE=..\..\include\ginclude.h
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiodrv.h
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiothiscallresolver.h
# End Source File
# Begin Source File
SOURCE=..\..\RtAudio.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project
@@ -0,0 +1,101 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "audioprobe"=.\audioprobe.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "duplex"=.\duplex.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "playraw"=.\playraw.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "playsaw"=.\playsaw.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "record"=.\record.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "testall"=.\testall.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "teststops"=.\teststops.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################
@@ -0,0 +1,158 @@
# Microsoft Developer Studio Project File - Name="testall" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=testall - Win32 Debug
!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 "testall.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 "testall.mak" CFG="testall - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "testall - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "testall - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "testall - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "testall___Win32_Release"
# PROP BASE Intermediate_Dir "testall___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /c
# 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 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 /subsystem:console /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 dsound.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "testall - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "testall___Win32_Debug"
# PROP BASE Intermediate_Dir "testall___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /GZ /c
# 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 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 /subsystem:console /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 dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "testall - Win32 Release"
# Name "testall - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\include\asio.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrivers.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\asiolist.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiothiscallresolver.cpp
# End Source File
# Begin Source File
SOURCE=..\..\RtAudio.cpp
# End Source File
# Begin Source File
SOURCE=..\testall.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\include\asio.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrivers.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrvr.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiolist.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiosys.h
# End Source File
# Begin Source File
SOURCE=..\..\include\ginclude.h
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiodrv.h
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiothiscallresolver.h
# End Source File
# Begin Source File
SOURCE=..\..\RtAudio.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project
@@ -0,0 +1,158 @@
# Microsoft Developer Studio Project File - Name="teststops" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=teststops - Win32 Debug
!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 "teststops.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 "teststops.mak" CFG="teststops - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "teststops - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "teststops - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "teststops - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "teststops___Win32_Release"
# PROP BASE Intermediate_Dir "teststops___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../" /I "../../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /c
# 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 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 /subsystem:console /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 dsound.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "teststops - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "teststops___Win32_Debug"
# PROP BASE Intermediate_Dir "teststops___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_ASIO__" /D "__WINDOWS_DS__" /D "__WINDOWS_WASAPI__" /YX /FD /GZ /c
# 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 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 /subsystem:console /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 dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "teststops - Win32 Release"
# Name "teststops - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=..\..\include\asio.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrivers.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\asiolist.cpp
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiothiscallresolver.cpp
# End Source File
# Begin Source File
SOURCE=..\..\RtAudio.cpp
# End Source File
# Begin Source File
SOURCE=..\teststops.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=..\..\include\asio.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrivers.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiodrvr.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiolist.h
# End Source File
# Begin Source File
SOURCE=..\..\include\asiosys.h
# End Source File
# Begin Source File
SOURCE=..\..\include\ginclude.h
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiodrv.h
# End Source File
# Begin Source File
SOURCE=..\..\include\iasiothiscallresolver.h
# End Source File
# Begin Source File
SOURCE=..\..\RtAudio.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project
@@ -0,0 +1,157 @@
/******************************************/
/*
apinames.cpp
by Jean Pierre Cimalando, 2018.
This program tests parts of RtAudio related
to API names, the conversion from name to API
and vice-versa.
*/
/******************************************/
#include "RtAudio.h"
#include <cctype>
#include <cstdlib>
#include <iostream>
int test_cpp() {
std::vector<RtAudio::Api> apis;
RtAudio::getCompiledApi( apis );
// ensure the known APIs return valid names
std::cout << "API names by identifier (C++):\n";
for ( size_t i = 0; i < apis.size() ; ++i ) {
const std::string name = RtAudio::getApiName(apis[i]);
if (name.empty()) {
std::cout << "Invalid name for API " << (int)apis[i] << "\n";
exit(1);
}
const std::string displayName = RtAudio::getApiDisplayName(apis[i]);
if (displayName.empty()) {
std::cout << "Invalid display name for API " << (int)apis[i] << "\n";
exit(1);
}
std::cout << "* " << (int)apis[i] << " '" << name << "': '" << displayName << "'\n";
}
// ensure unknown APIs return the empty string
{
const std::string name = RtAudio::getApiName((RtAudio::Api)-1);
if (!name.empty()) {
std::cout << "Bad string for invalid API '" << name << "'\n";
exit(1);
}
const std::string displayName = RtAudio::getApiDisplayName((RtAudio::Api)-1);
if (displayName!="Unknown") {
std::cout << "Bad display string for invalid API '" << displayName << "'\n";
exit(1);
}
}
// try getting API identifier by name
std::cout << "API identifiers by name (C++):\n";
for ( size_t i = 0; i < apis.size() ; ++i ) {
std::string name = RtAudio::getApiName(apis[i]);
if ( RtAudio::getCompiledApiByName(name) != apis[i] ) {
std::cout << "Bad identifier for API '" << name << "'\n";
exit( 1 );
}
std::cout << "* '" << name << "': " << (int)apis[i] << "\n";
for ( size_t j = 0; j < name.size(); ++j )
name[j] = (j & 1) ? toupper(name[j]) : tolower(name[j]);
RtAudio::Api api = RtAudio::getCompiledApiByName(name);
if ( api != RtAudio::UNSPECIFIED ) {
std::cout << "Identifier " << (int)api << " for invalid API '" << name << "'\n";
exit( 1 );
}
}
// try getting an API identifier by unknown name
{
RtAudio::Api api;
api = RtAudio::getCompiledApiByName("");
if ( api != RtAudio::UNSPECIFIED ) {
std::cout << "Bad identifier for unknown API name\n";
exit( 1 );
}
}
return 0;
}
#include "rtaudio_c.h"
int test_c() {
const rtaudio_api_t *apis = rtaudio_compiled_api();
// ensure the known APIs return valid names
std::cout << "API names by identifier (C):\n";
for ( size_t i = 0; apis[i] != RTAUDIO_API_UNSPECIFIED; ++i) {
const std::string name = rtaudio_api_name(apis[i]);
if (name.empty()) {
std::cout << "Invalid name for API " << (int)apis[i] << "\n";
exit(1);
}
const std::string displayName = rtaudio_api_display_name(apis[i]);
if (displayName.empty()) {
std::cout << "Invalid display name for API " << (int)apis[i] << "\n";
exit(1);
}
std::cout << "* " << (int)apis[i] << " '" << name << "': '" << displayName << "'\n";
}
// ensure unknown APIs return the empty string
{
const char *s = rtaudio_api_name((rtaudio_api_t)-1);
const std::string name(s?s:"");
if (!name.empty()) {
std::cout << "Bad string for invalid API '" << name << "'\n";
exit(1);
}
s = rtaudio_api_display_name((rtaudio_api_t)-1);
const std::string displayName(s?s:"");
if (displayName!="Unknown") {
std::cout << "Bad display string for invalid API '" << displayName << "'\n";
exit(1);
}
}
// try getting API identifier by name
std::cout << "API identifiers by name (C):\n";
for ( size_t i = 0; apis[i] != RTAUDIO_API_UNSPECIFIED ; ++i ) {
const char *s = rtaudio_api_name(apis[i]);
std::string name(s?s:"");
if ( rtaudio_compiled_api_by_name(name.c_str()) != apis[i] ) {
std::cout << "Bad identifier for API '" << name << "'\n";
exit( 1 );
}
std::cout << "* '" << name << "': " << (int)apis[i] << "\n";
for ( size_t j = 0; j < name.size(); ++j )
name[j] = (j & 1) ? toupper(name[j]) : tolower(name[j]);
rtaudio_api_t api = rtaudio_compiled_api_by_name(name.c_str());
if ( api != RTAUDIO_API_UNSPECIFIED ) {
std::cout << "Identifier " << (int)api << " for invalid API '" << name << "'\n";
exit( 1 );
}
}
// try getting an API identifier by unknown name
{
rtaudio_api_t api;
api = rtaudio_compiled_api_by_name("");
if ( api != RTAUDIO_API_UNSPECIFIED ) {
std::cout << "Bad identifier for unknown API name\n";
exit( 1 );
}
}
return 0;
}
int main()
{
test_cpp();
test_c();
}
@@ -0,0 +1,104 @@
/******************************************/
/*
audioprobe.cpp
by Gary P. Scavone, 2001
Probe audio system and prints device info.
*/
/******************************************/
#include "RtAudio.h"
#include <iostream>
#include <map>
std::vector< RtAudio::Api > listApis()
{
std::vector< RtAudio::Api > apis;
RtAudio :: getCompiledApi( apis );
std::cout << "\nCompiled APIs:\n";
for ( size_t i=0; i<apis.size(); i++ )
std::cout << i << ". " << RtAudio::getApiDisplayName(apis[i])
<< " (" << RtAudio::getApiName(apis[i]) << ")" << std::endl;
return apis;
}
void listDevices(RtAudio::Api api)
{
RtAudio audio(api);
RtAudio::DeviceInfo info;
std::cout << "\nAPI: " << RtAudio::getApiDisplayName(audio.getCurrentApi()) << std::endl;
unsigned int devices = audio.getDeviceCount();
std::cout << "\nFound " << devices << " device(s) ...\n";
for (unsigned int i=0; i<devices; i++) {
info = audio.getDeviceInfo(i);
std::cout << "\nDevice Name = " << info.name << '\n';
std::cout << "Device ID = " << i << '\n';
if ( info.probed == false )
std::cout << "Probe Status = UNsuccessful\n";
else {
std::cout << "Probe Status = Successful\n";
std::cout << "Output Channels = " << info.outputChannels << '\n';
std::cout << "Input Channels = " << info.inputChannels << '\n';
std::cout << "Duplex Channels = " << info.duplexChannels << '\n';
if ( info.isDefaultOutput ) std::cout << "This is the default output device.\n";
else std::cout << "This is NOT the default output device.\n";
if ( info.isDefaultInput ) std::cout << "This is the default input device.\n";
else std::cout << "This is NOT the default input device.\n";
if ( info.nativeFormats == 0 )
std::cout << "No natively supported data formats(?)!";
else {
std::cout << "Natively supported data formats:\n";
if ( info.nativeFormats & RTAUDIO_SINT8 )
std::cout << " 8-bit int\n";
if ( info.nativeFormats & RTAUDIO_SINT16 )
std::cout << " 16-bit int\n";
if ( info.nativeFormats & RTAUDIO_SINT24 )
std::cout << " 24-bit int\n";
if ( info.nativeFormats & RTAUDIO_SINT32 )
std::cout << " 32-bit int\n";
if ( info.nativeFormats & RTAUDIO_FLOAT32 )
std::cout << " 32-bit float\n";
if ( info.nativeFormats & RTAUDIO_FLOAT64 )
std::cout << " 64-bit float\n";
}
if ( info.sampleRates.size() < 1 )
std::cout << "No supported sample rates found!";
else {
std::cout << "Supported sample rates = ";
for (unsigned int j=0; j<info.sampleRates.size(); j++)
std::cout << info.sampleRates[j] << " ";
}
std::cout << std::endl;
if ( info.preferredSampleRate == 0 )
std::cout << "No preferred sample rate found!" << std::endl;
else
std::cout << "Preferred sample rate = " << info.preferredSampleRate << std::endl;
}
}
}
int main(int argc, char *argv[])
{
std::cout << "\nRtAudio Version " << RtAudio::getVersion() << std::endl;
std::vector< RtAudio::Api > apis = listApis();
for ( size_t api=0; api < apis.size(); api++ )
{
errno = 0;
char *s;
if (argc < 2
|| apis[api] == RtAudio::getCompiledApiByName(argv[1])
|| (api == std::strtoul(argv[1], &s, 10) && argv[1] != s && !errno))
listDevices(apis[api]);
}
std::cout << std::endl;
return 0;
}
@@ -0,0 +1,139 @@
/******************************************/
/*
duplex.cpp
by Gary P. Scavone, 2006-2007.
This program opens a duplex stream and passes
input directly through to the output.
*/
/******************************************/
#include "RtAudio.h"
#include <iostream>
#include <cstdlib>
#include <cstring>
/*
typedef char MY_TYPE;
#define FORMAT RTAUDIO_SINT8
*/
typedef signed short MY_TYPE;
#define FORMAT RTAUDIO_SINT16
/*
typedef S24 MY_TYPE;
#define FORMAT RTAUDIO_SINT24
typedef signed long MY_TYPE;
#define FORMAT RTAUDIO_SINT32
typedef float MY_TYPE;
#define FORMAT RTAUDIO_FLOAT32
typedef double MY_TYPE;
#define FORMAT RTAUDIO_FLOAT64
*/
void usage( void ) {
// Error function in case of incorrect command-line
// argument specifications
std::cout << "\nuseage: duplex N fs <iDevice> <oDevice> <iChannelOffset> <oChannelOffset>\n";
std::cout << " where N = number of channels,\n";
std::cout << " fs = the sample rate,\n";
std::cout << " iDevice = optional input device to use (default = 0),\n";
std::cout << " oDevice = optional output device to use (default = 0),\n";
std::cout << " iChannelOffset = an optional input channel offset (default = 0),\n";
std::cout << " and oChannelOffset = optional output channel offset (default = 0).\n\n";
exit( 0 );
}
int inout( void *outputBuffer, void *inputBuffer, unsigned int /*nBufferFrames*/,
double /*streamTime*/, RtAudioStreamStatus status, void *data )
{
// Since the number of input and output channels is equal, we can do
// a simple buffer copy operation here.
if ( status ) std::cout << "Stream over/underflow detected." << std::endl;
unsigned int *bytes = (unsigned int *) data;
memcpy( outputBuffer, inputBuffer, *bytes );
return 0;
}
int main( int argc, char *argv[] )
{
unsigned int channels, fs, bufferBytes, oDevice = 0, iDevice = 0, iOffset = 0, oOffset = 0;
// Minimal command-line checking
if (argc < 3 || argc > 7 ) usage();
RtAudio adac;
if ( adac.getDeviceCount() < 1 ) {
std::cout << "\nNo audio devices found!\n";
exit( 1 );
}
channels = (unsigned int) atoi(argv[1]);
fs = (unsigned int) atoi(argv[2]);
if ( argc > 3 )
iDevice = (unsigned int) atoi(argv[3]);
if ( argc > 4 )
oDevice = (unsigned int) atoi(argv[4]);
if ( argc > 5 )
iOffset = (unsigned int) atoi(argv[5]);
if ( argc > 6 )
oOffset = (unsigned int) atoi(argv[6]);
// Let RtAudio print messages to stderr.
adac.showWarnings( true );
// Set the same number of channels for both input and output.
unsigned int bufferFrames = 512;
RtAudio::StreamParameters iParams, oParams;
iParams.deviceId = iDevice;
iParams.nChannels = channels;
iParams.firstChannel = iOffset;
oParams.deviceId = oDevice;
oParams.nChannels = channels;
oParams.firstChannel = oOffset;
if ( iDevice == 0 )
iParams.deviceId = adac.getDefaultInputDevice();
if ( oDevice == 0 )
oParams.deviceId = adac.getDefaultOutputDevice();
RtAudio::StreamOptions options;
//options.flags |= RTAUDIO_NONINTERLEAVED;
try {
adac.openStream( &oParams, &iParams, FORMAT, fs, &bufferFrames, &inout, (void *)&bufferBytes, &options );
}
catch ( RtAudioError& e ) {
std::cout << '\n' << e.getMessage() << '\n' << std::endl;
exit( 1 );
}
// Test RtAudio functionality for reporting latency.
std::cout << "\nStream latency = " << adac.getStreamLatency() << " frames" << std::endl;
bufferBytes = bufferFrames * channels * sizeof( MY_TYPE );
try {
adac.startStream();
char input;
std::cout << "\nRunning ... press <enter> to quit (buffer frames = " << bufferFrames << ").\n";
std::cin.get(input);
// Stop the stream.
adac.stopStream();
}
catch ( RtAudioError& e ) {
std::cout << '\n' << e.getMessage() << '\n' << std::endl;
goto cleanup;
}
cleanup:
if ( adac.isStreamOpen() ) adac.closeStream();
return 0;
}
@@ -0,0 +1,10 @@
apinames = executable('apinames', 'apinames.cpp', dependencies: rtaudio_dep)
test('API names', apinames)
audioprobe = executable('audioprobe', 'audioprobe.cpp', dependencies: rtaudio_dep)
duplex = executable('duplex', 'duplex.cpp', dependencies: rtaudio_dep)
playraw = executable('playraw', 'playraw.cpp', dependencies: rtaudio_dep)
playsaw = executable('playsaw', 'playsaw.cpp', dependencies: rtaudio_dep)
record = executable('record', 'record.cpp', dependencies: rtaudio_dep)
testall = executable('testall', 'testall.cpp', dependencies: rtaudio_dep)
teststops = executable('teststops', 'teststops.cpp', dependencies: rtaudio_dep)
@@ -0,0 +1,152 @@
/******************************************/
/*
playraw.cpp
by Gary P. Scavone, 2007
Play a specified raw file. It is necessary
that the file be of the same data format as
defined below.
*/
/******************************************/
#include "RtAudio.h"
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <stdio.h>
/*
typedef char MY_TYPE;
#define FORMAT RTAUDIO_SINT8
#define SCALE 127.0
*/
typedef signed short MY_TYPE;
#define FORMAT RTAUDIO_SINT16
#define SCALE 32767.0
/*
typedef S24 MY_TYPE;
#define FORMAT RTAUDIO_SINT24
#define SCALE 8388607.0
typedef signed int MY_TYPE;
#define FORMAT RTAUDIO_SINT32
#define SCALE 2147483647.0
typedef float MY_TYPE;
#define FORMAT RTAUDIO_FLOAT32
#define SCALE 1.0;
typedef double MY_TYPE;
#define FORMAT RTAUDIO_FLOAT64
#define SCALE 1.0;
*/
// Platform-dependent sleep routines.
#if defined( WIN32 )
#include <windows.h>
#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds )
#else // Unix variants
#include <unistd.h>
#define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )
#endif
void usage( void ) {
// Error function in case of incorrect command-line
// argument specifications
std::cout << "\nuseage: playraw N fs file <device> <channelOffset>\n";
std::cout << " where N = number of channels,\n";
std::cout << " fs = the sample rate, \n";
std::cout << " file = the raw file to play,\n";
std::cout << " device = optional device to use (default = 0),\n";
std::cout << " and channelOffset = an optional channel offset on the device (default = 0).\n\n";
exit( 0 );
}
struct OutputData {
FILE *fd;
unsigned int channels;
};
// Interleaved buffers
int output( void *outputBuffer, void * /*inputBuffer*/, unsigned int nBufferFrames,
double /*streamTime*/, RtAudioStreamStatus /*status*/, void *data )
{
OutputData *oData = (OutputData*) data;
// In general, it's not a good idea to do file input in the audio
// callback function but I'm doing it here because I don't know the
// length of the file we are reading.
unsigned int count = fread( outputBuffer, oData->channels * sizeof( MY_TYPE ), nBufferFrames, oData->fd);
if ( count < nBufferFrames ) {
unsigned int bytes = (nBufferFrames - count) * oData->channels * sizeof( MY_TYPE );
unsigned int startByte = count * oData->channels * sizeof( MY_TYPE );
memset( (char *)(outputBuffer)+startByte, 0, bytes );
return 1;
}
return 0;
}
int main( int argc, char *argv[] )
{
unsigned int channels, fs, bufferFrames, device = 0, offset = 0;
char *file;
// minimal command-line checking
if ( argc < 4 || argc > 6 ) usage();
RtAudio dac;
if ( dac.getDeviceCount() < 1 ) {
std::cout << "\nNo audio devices found!\n";
exit( 0 );
}
channels = (unsigned int) atoi( argv[1]) ;
fs = (unsigned int) atoi( argv[2] );
file = argv[3];
if ( argc > 4 )
device = (unsigned int) atoi( argv[4] );
if ( argc > 5 )
offset = (unsigned int) atoi( argv[5] );
OutputData data;
data.fd = fopen( file, "rb" );
if ( !data.fd ) {
std::cout << "Unable to find or open file!\n";
exit( 1 );
}
// Set our stream parameters for output only.
bufferFrames = 512;
RtAudio::StreamParameters oParams;
oParams.deviceId = device;
oParams.nChannels = channels;
oParams.firstChannel = offset;
if ( device == 0 )
oParams.deviceId = dac.getDefaultOutputDevice();
data.channels = channels;
try {
dac.openStream( &oParams, NULL, FORMAT, fs, &bufferFrames, &output, (void *)&data );
dac.startStream();
}
catch ( RtAudioError& e ) {
std::cout << '\n' << e.getMessage() << '\n' << std::endl;
goto cleanup;
}
std::cout << "\nPlaying raw file " << file << " (buffer frames = " << bufferFrames << ")." << std::endl;
while ( 1 ) {
SLEEP( 100 ); // wake every 100 ms to check if we're done
if ( dac.isStreamRunning() == false ) break;
}
cleanup:
fclose( data.fd );
dac.closeStream();
return 0;
}
@@ -0,0 +1,217 @@
/******************************************/
/*
playsaw.cpp
by Gary P. Scavone, 2006
This program will output sawtooth waveforms
of different frequencies on each channel.
*/
/******************************************/
#include "RtAudio.h"
#include <iostream>
#include <cstdlib>
/*
typedef char MY_TYPE;
#define FORMAT RTAUDIO_SINT8
#define SCALE 127.0
*/
typedef signed short MY_TYPE;
#define FORMAT RTAUDIO_SINT16
#define SCALE 32767.0
/*
typedef S24 MY_TYPE;
#define FORMAT RTAUDIO_SINT24
#define SCALE 8388607.0
typedef signed long MY_TYPE;
#define FORMAT RTAUDIO_SINT32
#define SCALE 2147483647.0
typedef float MY_TYPE;
#define FORMAT RTAUDIO_FLOAT32
#define SCALE 1.0
typedef double MY_TYPE;
#define FORMAT RTAUDIO_FLOAT64
#define SCALE 1.0
*/
// Platform-dependent sleep routines.
#if defined( WIN32 )
#include <windows.h>
#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds )
#else // Unix variants
#include <unistd.h>
#define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )
#endif
#define BASE_RATE 0.005
#define TIME 1.0
void usage( void ) {
// Error function in case of incorrect command-line
// argument specifications
std::cout << "\nuseage: playsaw N fs <device> <channelOffset> <time>\n";
std::cout << " where N = number of channels,\n";
std::cout << " fs = the sample rate,\n";
std::cout << " device = optional device to use (default = 0),\n";
std::cout << " channelOffset = an optional channel offset on the device (default = 0),\n";
std::cout << " and time = an optional time duration in seconds (default = no limit).\n\n";
exit( 0 );
}
void errorCallback( RtAudioError::Type type, const std::string &errorText )
{
// This example error handling function does exactly the same thing
// as the embedded RtAudio::error() function.
std::cout << "in errorCallback" << std::endl;
if ( type == RtAudioError::WARNING )
std::cerr << '\n' << errorText << "\n\n";
else if ( type != RtAudioError::WARNING )
throw( RtAudioError( errorText, type ) );
}
unsigned int channels;
RtAudio::StreamOptions options;
unsigned int frameCounter = 0;
bool checkCount = false;
unsigned int nFrames = 0;
const unsigned int callbackReturnValue = 1;
//#define USE_INTERLEAVED
#if defined( USE_INTERLEAVED )
// Interleaved buffers
int saw( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
double streamTime, RtAudioStreamStatus status, void *data )
{
unsigned int i, j;
extern unsigned int channels;
MY_TYPE *buffer = (MY_TYPE *) outputBuffer;
double *lastValues = (double *) data;
if ( status )
std::cout << "Stream underflow detected!" << std::endl;
for ( i=0; i<nBufferFrames; i++ ) {
for ( j=0; j<channels; j++ ) {
*buffer++ = (MY_TYPE) (lastValues[j] * SCALE * 0.5);
lastValues[j] += BASE_RATE * (j+1+(j*0.1));
if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;
}
}
frameCounter += nBufferFrames;
if ( checkCount && ( frameCounter >= nFrames ) ) return callbackReturnValue;
return 0;
}
#else // Use non-interleaved buffers
int saw( void *outputBuffer, void * /*inputBuffer*/, unsigned int nBufferFrames,
double /*streamTime*/, RtAudioStreamStatus status, void *data )
{
unsigned int i, j;
extern unsigned int channels;
MY_TYPE *buffer = (MY_TYPE *) outputBuffer;
double *lastValues = (double *) data;
if ( status )
std::cout << "Stream underflow detected!" << std::endl;
double increment;
for ( j=0; j<channels; j++ ) {
increment = BASE_RATE * (j+1+(j*0.1));
for ( i=0; i<nBufferFrames; i++ ) {
*buffer++ = (MY_TYPE) (lastValues[j] * SCALE * 0.5);
lastValues[j] += increment;
if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;
}
}
frameCounter += nBufferFrames;
if ( checkCount && ( frameCounter >= nFrames ) ) return callbackReturnValue;
return 0;
}
#endif
int main( int argc, char *argv[] )
{
unsigned int bufferFrames, fs, device = 0, offset = 0;
// minimal command-line checking
if (argc < 3 || argc > 6 ) usage();
RtAudio dac;
if ( dac.getDeviceCount() < 1 ) {
std::cout << "\nNo audio devices found!\n";
exit( 1 );
}
channels = (unsigned int) atoi( argv[1] );
fs = (unsigned int) atoi( argv[2] );
if ( argc > 3 )
device = (unsigned int) atoi( argv[3] );
if ( argc > 4 )
offset = (unsigned int) atoi( argv[4] );
if ( argc > 5 )
nFrames = (unsigned int) (fs * atof( argv[5] ));
if ( nFrames > 0 ) checkCount = true;
double *data = (double *) calloc( channels, sizeof( double ) );
// Let RtAudio print messages to stderr.
dac.showWarnings( true );
// Set our stream parameters for output only.
bufferFrames = 512;
RtAudio::StreamParameters oParams;
oParams.deviceId = device;
oParams.nChannels = channels;
oParams.firstChannel = offset;
if ( device == 0 )
oParams.deviceId = dac.getDefaultOutputDevice();
options.flags = RTAUDIO_HOG_DEVICE;
options.flags |= RTAUDIO_SCHEDULE_REALTIME;
#if !defined( USE_INTERLEAVED )
options.flags |= RTAUDIO_NONINTERLEAVED;
#endif
try {
dac.openStream( &oParams, NULL, FORMAT, fs, &bufferFrames, &saw, (void *)data, &options, &errorCallback );
dac.startStream();
}
catch ( RtAudioError& e ) {
e.printMessage();
goto cleanup;
}
if ( checkCount ) {
while ( dac.isStreamRunning() == true ) SLEEP( 100 );
}
else {
char input;
//std::cout << "Stream latency = " << dac.getStreamLatency() << "\n" << std::endl;
std::cout << "\nPlaying ... press <enter> to quit (buffer size = " << bufferFrames << ").\n";
std::cin.get( input );
try {
// Stop the stream
dac.stopStream();
}
catch ( RtAudioError& e ) {
e.printMessage();
}
}
cleanup:
if ( dac.isStreamOpen() ) dac.closeStream();
free( data );
return 0;
}
@@ -0,0 +1,174 @@
/******************************************/
/*
record.cpp
by Gary P. Scavone, 2007
This program records audio from a device and writes it to a
header-less binary file. Use the 'playraw', with the same
parameters and format settings, to playback the audio.
*/
/******************************************/
#include "RtAudio.h"
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <stdio.h>
/*
typedef char MY_TYPE;
#define FORMAT RTAUDIO_SINT8
*/
typedef signed short MY_TYPE;
#define FORMAT RTAUDIO_SINT16
/*
typedef S24 MY_TYPE;
#define FORMAT RTAUDIO_SINT24
typedef signed long MY_TYPE;
#define FORMAT RTAUDIO_SINT32
typedef float MY_TYPE;
#define FORMAT RTAUDIO_FLOAT32
typedef double MY_TYPE;
#define FORMAT RTAUDIO_FLOAT64
*/
// Platform-dependent sleep routines.
#if defined( WIN32 )
#include <windows.h>
#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds )
#else // Unix variants
#include <unistd.h>
#define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )
#endif
void usage( void ) {
// Error function in case of incorrect command-line
// argument specifications
std::cout << "\nuseage: record N fs <duration> <device> <channelOffset>\n";
std::cout << " where N = number of channels,\n";
std::cout << " fs = the sample rate,\n";
std::cout << " duration = optional time in seconds to record (default = 2.0),\n";
std::cout << " device = optional device to use (default = 0),\n";
std::cout << " and channelOffset = an optional channel offset on the device (default = 0).\n\n";
exit( 0 );
}
struct InputData {
MY_TYPE* buffer;
unsigned long bufferBytes;
unsigned long totalFrames;
unsigned long frameCounter;
unsigned int channels;
};
// Interleaved buffers
int input( void * /*outputBuffer*/, void *inputBuffer, unsigned int nBufferFrames,
double /*streamTime*/, RtAudioStreamStatus /*status*/, void *data )
{
InputData *iData = (InputData *) data;
// Simply copy the data to our allocated buffer.
unsigned int frames = nBufferFrames;
if ( iData->frameCounter + nBufferFrames > iData->totalFrames ) {
frames = iData->totalFrames - iData->frameCounter;
iData->bufferBytes = frames * iData->channels * sizeof( MY_TYPE );
}
unsigned long offset = iData->frameCounter * iData->channels;
memcpy( iData->buffer+offset, inputBuffer, iData->bufferBytes );
iData->frameCounter += frames;
if ( iData->frameCounter >= iData->totalFrames ) return 2;
return 0;
}
int main( int argc, char *argv[] )
{
unsigned int channels, fs, bufferFrames, device = 0, offset = 0;
double time = 2.0;
FILE *fd;
// minimal command-line checking
if ( argc < 3 || argc > 6 ) usage();
RtAudio adc;
if ( adc.getDeviceCount() < 1 ) {
std::cout << "\nNo audio devices found!\n";
exit( 1 );
}
channels = (unsigned int) atoi( argv[1] );
fs = (unsigned int) atoi( argv[2] );
if ( argc > 3 )
time = (double) atof( argv[3] );
if ( argc > 4 )
device = (unsigned int) atoi( argv[4] );
if ( argc > 5 )
offset = (unsigned int) atoi( argv[5] );
// Let RtAudio print messages to stderr.
adc.showWarnings( true );
// Set our stream parameters for input only.
bufferFrames = 512;
RtAudio::StreamParameters iParams;
if ( device == 0 )
iParams.deviceId = adc.getDefaultInputDevice();
else
iParams.deviceId = device;
iParams.nChannels = channels;
iParams.firstChannel = offset;
InputData data;
data.buffer = 0;
try {
adc.openStream( NULL, &iParams, FORMAT, fs, &bufferFrames, &input, (void *)&data );
}
catch ( RtAudioError& e ) {
std::cout << '\n' << e.getMessage() << '\n' << std::endl;
goto cleanup;
}
data.bufferBytes = bufferFrames * channels * sizeof( MY_TYPE );
data.totalFrames = (unsigned long) (fs * time);
data.frameCounter = 0;
data.channels = channels;
unsigned long totalBytes;
totalBytes = data.totalFrames * channels * sizeof( MY_TYPE );
// Allocate the entire data buffer before starting stream.
data.buffer = (MY_TYPE*) malloc( totalBytes );
if ( data.buffer == 0 ) {
std::cout << "Memory allocation error ... quitting!\n";
goto cleanup;
}
try {
adc.startStream();
}
catch ( RtAudioError& e ) {
std::cout << '\n' << e.getMessage() << '\n' << std::endl;
goto cleanup;
}
std::cout << "\nRecording for " << time << " seconds ... writing file 'record.raw' (buffer frames = " << bufferFrames << ")." << std::endl;
while ( adc.isStreamRunning() ) {
SLEEP( 100 ); // wake every 100 ms to check if we're done
}
// Now write the entire data to the file.
fd = fopen( "record.raw", "wb" );
fwrite( data.buffer, sizeof( MY_TYPE ), data.totalFrames * channels, fd );
fclose( fd );
cleanup:
if ( adc.isStreamOpen() ) adc.closeStream();
if ( data.buffer ) free( data.buffer );
return 0;
}
@@ -0,0 +1,233 @@
/******************************************/
/*
testall.cpp
by Gary P. Scavone, 2007-2008
This program will make a variety of calls
to extensively test RtAudio functionality.
*/
/******************************************/
#include "RtAudio.h"
#include <iostream>
#include <cstdlib>
#include <cstring>
#define BASE_RATE 0.005
#define TIME 1.0
void usage( void ) {
// Error function in case of incorrect command-line
// argument specifications
std::cout << "\nuseage: testall N fs <iDevice> <oDevice> <iChannelOffset> <oChannelOffset>\n";
std::cout << " where N = number of channels,\n";
std::cout << " fs = the sample rate,\n";
std::cout << " iDevice = optional input device to use (default = 0),\n";
std::cout << " oDevice = optional output device to use (default = 0),\n";
std::cout << " iChannelOffset = an optional input channel offset (default = 0),\n";
std::cout << " and oChannelOffset = optional output channel offset (default = 0).\n\n";
exit( 0 );
}
unsigned int channels;
// Interleaved buffers
int sawi( void *outputBuffer, void * /*inputBuffer*/, unsigned int nBufferFrames,
double /*streamTime*/, RtAudioStreamStatus status, void *data )
{
unsigned int i, j;
extern unsigned int channels;
double *buffer = (double *) outputBuffer;
double *lastValues = (double *) data;
if ( status )
std::cout << "Stream underflow detected!" << std::endl;
for ( i=0; i<nBufferFrames; i++ ) {
for ( j=0; j<channels; j++ ) {
*buffer++ = (double) lastValues[j];
lastValues[j] += BASE_RATE * (j+1+(j*0.1));
if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;
}
}
return 0;
}
// Non-interleaved buffers
int sawni( void *outputBuffer, void * /*inputBuffer*/, unsigned int nBufferFrames,
double /*streamTime*/, RtAudioStreamStatus status, void *data )
{
unsigned int i, j;
extern unsigned int channels;
double *buffer = (double *) outputBuffer;
double *lastValues = (double *) data;
if ( status )
std::cout << "Stream underflow detected!" << std::endl;
double increment;
for ( j=0; j<channels; j++ ) {
increment = BASE_RATE * (j+1+(j*0.1));
for ( i=0; i<nBufferFrames; i++ ) {
*buffer++ = (double) lastValues[j];
lastValues[j] += increment;
if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;
}
}
return 0;
}
int inout( void *outputBuffer, void *inputBuffer, unsigned int /*nBufferFrames*/,
double /*streamTime*/, RtAudioStreamStatus status, void *data )
{
// Since the number of input and output channels is equal, we can do
// a simple buffer copy operation here.
if ( status ) std::cout << "Stream over/underflow detected." << std::endl;
unsigned int *bytes = (unsigned int *) data;
memcpy( outputBuffer, inputBuffer, *bytes );
return 0;
}
int main( int argc, char *argv[] )
{
unsigned int bufferFrames, fs, oDevice = 0, iDevice = 0, iOffset = 0, oOffset = 0;
char input;
// minimal command-line checking
if (argc < 3 || argc > 7 ) usage();
RtAudio dac;
if ( dac.getDeviceCount() < 1 ) {
std::cout << "\nNo audio devices found!\n";
exit( 1 );
}
channels = (unsigned int) atoi( argv[1] );
fs = (unsigned int) atoi( argv[2] );
if ( argc > 3 )
iDevice = (unsigned int) atoi( argv[3] );
if ( argc > 4 )
oDevice = (unsigned int) atoi(argv[4]);
if ( argc > 5 )
iOffset = (unsigned int) atoi(argv[5]);
if ( argc > 6 )
oOffset = (unsigned int) atoi(argv[6]);
double *data = (double *) calloc( channels, sizeof( double ) );
// Let RtAudio print messages to stderr.
dac.showWarnings( true );
// Set our stream parameters for output only.
bufferFrames = 512;
RtAudio::StreamParameters oParams, iParams;
oParams.deviceId = oDevice;
oParams.nChannels = channels;
oParams.firstChannel = oOffset;
if ( oDevice == 0 )
oParams.deviceId = dac.getDefaultOutputDevice();
RtAudio::StreamOptions options;
options.flags = RTAUDIO_HOG_DEVICE;
try {
dac.openStream( &oParams, NULL, RTAUDIO_FLOAT64, fs, &bufferFrames, &sawi, (void *)data, &options );
std::cout << "\nStream latency = " << dac.getStreamLatency() << std::endl;
// Start the stream
dac.startStream();
std::cout << "\nPlaying ... press <enter> to stop.\n";
std::cin.get( input );
// Stop the stream
dac.stopStream();
// Restart again
std::cout << "Press <enter> to restart.\n";
std::cin.get( input );
dac.startStream();
// Test abort function
std::cout << "Playing again ... press <enter> to abort.\n";
std::cin.get( input );
dac.abortStream();
// Restart another time
std::cout << "Press <enter> to restart again.\n";
std::cin.get( input );
dac.startStream();
std::cout << "Playing again ... press <enter> to close the stream.\n";
std::cin.get( input );
}
catch ( RtAudioError& e ) {
e.printMessage();
goto cleanup;
}
if ( dac.isStreamOpen() ) dac.closeStream();
// Test non-interleaved functionality
options.flags = RTAUDIO_NONINTERLEAVED;
try {
dac.openStream( &oParams, NULL, RTAUDIO_FLOAT64, fs, &bufferFrames, &sawni, (void *)data, &options );
std::cout << "Press <enter> to start non-interleaved playback.\n";
std::cin.get( input );
// Start the stream
dac.startStream();
std::cout << "\nPlaying ... press <enter> to stop.\n";
std::cin.get( input );
}
catch ( RtAudioError& e ) {
e.printMessage();
goto cleanup;
}
if ( dac.isStreamOpen() ) dac.closeStream();
// Now open a duplex stream.
unsigned int bufferBytes;
iParams.deviceId = iDevice;
iParams.nChannels = channels;
iParams.firstChannel = iOffset;
if ( iDevice == 0 )
iParams.deviceId = dac.getDefaultInputDevice();
options.flags = RTAUDIO_NONINTERLEAVED;
try {
dac.openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &inout, (void *)&bufferBytes, &options );
bufferBytes = bufferFrames * channels * 4;
std::cout << "Press <enter> to start duplex operation.\n";
std::cin.get( input );
// Start the stream
dac.startStream();
std::cout << "\nRunning ... press <enter> to stop.\n";
std::cin.get( input );
// Stop the stream
dac.stopStream();
std::cout << "\nStopped ... press <enter> to restart.\n";
std::cin.get( input );
// Restart the stream
dac.startStream();
std::cout << "\nRunning ... press <enter> to stop.\n";
std::cin.get( input );
}
catch ( RtAudioError& e ) {
e.printMessage();
}
cleanup:
if ( dac.isStreamOpen() ) dac.closeStream();
free( data );
return 0;
}
@@ -0,0 +1,271 @@
/******************************************/
/*
teststop.cpp
by Gary P. Scavone, 2011
This program starts and stops an RtAudio
stream many times in succession and in
different ways to to test its functionality.
*/
/******************************************/
#include "RtAudio.h"
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define PULSE_RATE 0.01 // seconds
#define RUNTIME 0.4 // seconds
#define PAUSETIME 0.1 // seconds
#define REPETITIONS 10
// Platform-dependent sleep routines.
#if defined( WIN32 )
#include <windows.h>
#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds )
#else // Unix variants
#include <unistd.h>
#define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )
#endif
void usage( void ) {
// Error function in case of incorrect command-line
// argument specifications
std::cout << "\nuseage: teststops N fs <iDevice> <oDevice> <iChannelOffset> <oChannelOffset>\n";
std::cout << " where N = number of channels,\n";
std::cout << " fs = the sample rate,\n";
std::cout << " iDevice = optional input device to use (default = 0),\n";
std::cout << " oDevice = optional output device to use (default = 0),\n";
std::cout << " iChannelOffset = an optional input channel offset (default = 0),\n";
std::cout << " and oChannelOffset = optional output channel offset (default = 0).\n\n";
exit( 0 );
}
struct MyData {
unsigned int channels;
unsigned int pulseCount;
unsigned int frameCounter;
unsigned int nFrames;
unsigned int returnValue;
};
// Interleaved buffers
int pulse( void *outputBuffer, void * /*inputBuffer*/, unsigned int nBufferFrames,
double /*streamTime*/, RtAudioStreamStatus status, void *mydata )
{
// Write out a pulse signal and ignore the input buffer.
unsigned int i, j;
float sample;
float *buffer = (float *) outputBuffer;
MyData *data = (MyData *) mydata;
if ( status ) std::cout << "Stream over/underflow detected!" << std::endl;
for ( i=0; i<nBufferFrames; i++ ) {
if ( data->frameCounter % data->pulseCount == 0 ) sample = 0.9f;
else sample = 0.0;
for ( j=0; j<data->channels; j++ )
*buffer++ = sample;
data->frameCounter++;
}
if ( data->frameCounter >= data->nFrames )
return data->returnValue;
else
return 0;
}
int main( int argc, char *argv[] )
{
unsigned int bufferFrames, fs, oDevice = 0, iDevice = 0, iOffset = 0, oOffset = 0;
unsigned int runtime, pausetime;
char input;
// minimal command-line checking
if (argc < 3 || argc > 7 ) usage();
RtAudio *adc = new RtAudio();
if ( adc->getDeviceCount() < 1 ) {
std::cout << "\nNo audio devices found!\n";
exit( 1 );
}
MyData mydata;
mydata.channels = (unsigned int) atoi( argv[1] );
fs = (unsigned int) atoi( argv[2] );
if ( argc > 3 )
iDevice = (unsigned int) atoi( argv[3] );
if ( argc > 4 )
oDevice = (unsigned int) atoi(argv[4]);
if ( argc > 5 )
iOffset = (unsigned int) atoi(argv[5]);
if ( argc > 6 )
oOffset = (unsigned int) atoi(argv[6]);
// Let RtAudio print messages to stderr.
adc->showWarnings( true );
runtime = static_cast<unsigned int>(RUNTIME * 1000);
pausetime = static_cast<unsigned int>(PAUSETIME * 1000);
// Set our stream parameters for a duplex stream.
bufferFrames = 512;
RtAudio::StreamParameters oParams, iParams;
oParams.deviceId = oDevice;
oParams.nChannels = mydata.channels;
oParams.firstChannel = oOffset;
iParams.deviceId = iDevice;
iParams.nChannels = mydata.channels;
iParams.firstChannel = iOffset;
if ( iDevice == 0 )
iParams.deviceId = adc->getDefaultInputDevice();
if ( oDevice == 0 )
oParams.deviceId = adc->getDefaultOutputDevice();
// First, test external stopStream() calls.
mydata.pulseCount = static_cast<unsigned int>(PULSE_RATE * fs);
mydata.nFrames = 50 * fs;
mydata.returnValue = 0;
try {
adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );
std::cout << "Press <enter> to start test.\n";
std::cin.get( input );
for (int i=0; i<REPETITIONS; i++ ) {
mydata.frameCounter = 0;
adc->startStream();
std::cout << "Stream started ... ";
SLEEP( runtime );
adc->stopStream();
std::cout << "stream externally stopped.\n";
SLEEP( pausetime );
}
}
catch ( RtAudioError& e ) {
e.printMessage();
goto cleanup;
}
adc->closeStream();
// Next, test internal stopStream() calls.
mydata.nFrames = (unsigned int) (RUNTIME * fs);
mydata.returnValue = 1;
try {
adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );
std::cin.clear();
fflush(stdin);
std::cout << "\nPress <enter> to continue test.\n";
std::cin.get( input );
for (int i=0; i<REPETITIONS; i++ ) {
mydata.frameCounter = 0;
adc->startStream();
std::cout << "Stream started ... ";
while ( adc->isStreamRunning() ) SLEEP( 5 );
std::cout << "stream stopped via callback return value = 1.\n";
SLEEP( pausetime );
}
}
catch ( RtAudioError& e ) {
e.printMessage();
goto cleanup;
}
adc->closeStream();
// Test internal abortStream() calls.
mydata.returnValue = 2;
try {
adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );
std::cin.clear();
fflush(stdin);
std::cout << "\nPress <enter> to continue test.\n";
std::cin.get( input );
for (int i=0; i<REPETITIONS; i++ ) {
mydata.frameCounter = 0;
adc->startStream();
std::cout << "Stream started ... ";
while ( adc->isStreamRunning() ) SLEEP( 5 );
std::cout << "stream aborted via callback return value = 2.\n";
SLEEP( pausetime );
}
}
catch ( RtAudioError& e ) {
e.printMessage();
goto cleanup;
}
adc->closeStream();
// Test consecutive stream re-opening.
mydata.returnValue = 0;
mydata.nFrames = 50 * fs;
try {
std::cin.clear();
fflush(stdin);
std::cout << "\nPress <enter> to continue test.\n";
std::cin.get( input );
for (int i=0; i<REPETITIONS; i++ ) {
adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );
mydata.frameCounter = 0;
adc->startStream();
std::cout << "New stream started ... ";
SLEEP( runtime );
adc->stopStream();
adc->closeStream();
std::cout << "stream stopped externally and closed.\n";
SLEEP( pausetime );
}
}
catch ( RtAudioError& e ) {
e.printMessage();
goto cleanup;
}
delete adc;
adc = 0;
// Test consecutive RtAudio creating and deletion.
try {
std::cin.clear();
fflush(stdin);
std::cout << "\nPress <enter> to continue test.\n";
std::cin.get( input );
for (int i=0; i<REPETITIONS; i++ ) {
adc = new RtAudio();
adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );
mydata.frameCounter = 0;
adc->startStream();
std::cout << "New instance and stream started ... ";
SLEEP( runtime );
adc->stopStream();
adc->closeStream();
delete adc;
adc = 0;
std::cout << "stream stopped and instance deleted.\n";
SLEEP( pausetime );
}
}
catch ( RtAudioError& e ) {
e.printMessage();
goto cleanup;
}
cleanup:
if ( adc && adc->isStreamOpen() ) adc->closeStream();
if ( adc ) delete adc;
return 0;
}