@@ -8,7 +8,7 @@ OBJECTS = RtAudio.o @objects@ | |||
STATIC = librtaudio.a | |||
SHARED = @sharedlib@ | |||
RELEASE = 4.0.11 | |||
RELEASE = 4.0.12 | |||
MAJOR = 4 | |||
LIBRARIES = $(STATIC) $(SHARED) | |||
@@ -28,9 +28,8 @@ $(LIBRARIES): $(OBJECTS) | |||
$(AR) ruv $(STATIC) $(OBJECTS) | |||
ranlib $(STATIC) | |||
$(CC) -fPIC @libflags@ $(OBJECTS) @LIBS@ | |||
$(LN) -s @sharedname@ $(SHARED) | |||
# $(CC) -shared $(OBJECTS) -o $(SHARED) @LIBS@ | |||
$(LN) -sf @sharedname@ $(SHARED) | |||
$(LN) -sf @sharedname@ $(SHARED).$(MAJOR) | |||
%.o : %.cpp | |||
$(CC) $(CFLAGS) $(DEFS) -c $(<) -o $@ | |||
@@ -48,7 +47,7 @@ distclean: | |||
$(RM) -f $(LIBRARIES) @sharedname@ $(SHARED)* | |||
$(RM) -f $(OBJECTS) | |||
$(RM) -f *~ | |||
$(RM) -rf config.log config.status autom4te.cache Makefile rtaudio-config | |||
$(RM) -rf config.log config.status autom4te.cache Makefile rtaudio-config librtaudio.pc | |||
cd tests && $(MAKE) distclean | |||
strip : | |||
@@ -10,7 +10,7 @@ | |||
RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/ | |||
RtAudio: realtime audio i/o C++ classes | |||
Copyright (c) 2001-2012 Gary P. Scavone | |||
Copyright (c) 2001-2013 Gary P. Scavone | |||
Permission is hereby granted, free of charge, to any person | |||
obtaining a copy of this software and associated documentation files | |||
@@ -42,8 +42,6 @@ | |||
\file RtAudio.h | |||
*/ | |||
// RtAudio: Version 4.0.11 | |||
#ifndef __RTAUDIO_H | |||
#define __RTAUDIO_H | |||
@@ -51,6 +49,9 @@ | |||
#include <vector> | |||
#include "RtError.h" | |||
// RtAudio version | |||
static const std::string VERSION( "4.0.12" ); | |||
/*! \typedef typedef unsigned long RtAudioFormat; | |||
\brief RtAudio data format type. | |||
@@ -59,12 +60,10 @@ | |||
internal routines will automatically take care of any necessary | |||
byte-swapping between the host format and the soundcard. Thus, | |||
endian-ness is not a concern in the following format definitions. | |||
Note that 24-bit data is expected to be encapsulated in a 32-bit | |||
format. | |||
- \e RTAUDIO_SINT8: 8-bit signed integer. | |||
- \e RTAUDIO_SINT16: 16-bit signed integer. | |||
- \e RTAUDIO_SINT24: Lower 3 bytes of 32-bit signed integer. | |||
- \e RTAUDIO_SINT24: 24-bit signed integer. | |||
- \e RTAUDIO_SINT32: 32-bit signed integer. | |||
- \e RTAUDIO_FLOAT32: Normalized between plus/minus 1.0. | |||
- \e RTAUDIO_FLOAT64: Normalized between plus/minus 1.0. | |||
@@ -72,7 +71,7 @@ | |||
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; // Lower 3 bytes of 32-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. | |||
@@ -186,6 +185,12 @@ typedef int (*RtAudioCallback)( void *outputBuffer, void *inputBuffer, | |||
RtAudioStreamStatus status, | |||
void *userData ); | |||
//! RtAudio error callback function prototype. | |||
/*! | |||
\param type Type of error. | |||
\param errorText Error description. | |||
*/ | |||
typedef void (*RtAudioErrorCallback)( RtError::Type type, const std::string &errorText ); | |||
// **************************************************************** // | |||
// | |||
@@ -316,6 +321,9 @@ class RtAudio | |||
: flags(0), numberOfBuffers(0), priority(0) {} | |||
}; | |||
//! A static function to determine the current RtAudio version. | |||
static std::string getVersion( void ) { return VERSION; } | |||
//! A static function to determine the available compiled audio APIs. | |||
/*! | |||
The values returned in the std::vector can be compared against | |||
@@ -423,12 +431,14 @@ class RtAudio | |||
chosen. If the RTAUDIO_MINIMIZE_LATENCY flag bit is set, the | |||
lowest allowable value is used. The actual value used is | |||
returned via the structure argument. The parameter is API dependent. | |||
\param errorCallback A client-defined function that will be invoked | |||
when an error has occured. | |||
*/ | |||
void openStream( RtAudio::StreamParameters *outputParameters, | |||
RtAudio::StreamParameters *inputParameters, | |||
RtAudioFormat format, unsigned int sampleRate, | |||
unsigned int *bufferFrames, RtAudioCallback callback, | |||
void *userData = NULL, RtAudio::StreamOptions *options = NULL ); | |||
void *userData = NULL, RtAudio::StreamOptions *options = NULL, RtAudioErrorCallback errorCallback = NULL ); | |||
//! A function that closes a stream and frees any associated stream memory. | |||
/*! | |||
@@ -535,12 +545,15 @@ struct CallbackInfo { | |||
ThreadHandle thread; | |||
void *callback; | |||
void *userData; | |||
void *errorCallback; | |||
void *apiInfo; // void pointer for API specific callback information | |||
bool isRunning; | |||
bool doRealtime; | |||
int priority; | |||
// Default constructor. | |||
CallbackInfo() | |||
:object(0), callback(0), userData(0), apiInfo(0), isRunning(false) {} | |||
:object(0), callback(0), userData(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false) {} | |||
}; | |||
// **************************************************************** // | |||
@@ -557,6 +570,36 @@ struct CallbackInfo { | |||
// | |||
// **************************************************************** // | |||
#pragma pack(push, 1) | |||
class S24 { | |||
protected: | |||
unsigned char c3[3]; | |||
public: | |||
S24() {} | |||
S24& operator = ( const int& i ) { | |||
c3[0] = (i & 0x000000ff); | |||
c3[1] = (i & 0x0000ff00) >> 8; | |||
c3[2] = (i & 0x00ff0000) >> 16; | |||
return *this; | |||
} | |||
S24( const S24& v ) { *this = v; } | |||
S24( const double& d ) { *this = (int) d; } | |||
S24( const float& f ) { *this = (int) f; } | |||
S24( const signed short& s ) { *this = (int) s; } | |||
S24( const char& c ) { *this = (int) c; } | |||
int asInt() { | |||
int i = c3[0] | (c3[1] << 8) | (c3[2] << 16); | |||
if (i & 0x800000) i |= ~0xffffff; | |||
return i; | |||
} | |||
}; | |||
#pragma pack(pop) | |||
#if defined( HAVE_GETTIMEOFDAY ) | |||
#include <sys/time.h> | |||
#endif | |||
@@ -578,7 +621,8 @@ public: | |||
RtAudio::StreamParameters *inputParameters, | |||
RtAudioFormat format, unsigned int sampleRate, | |||
unsigned int *bufferFrames, RtAudioCallback callback, | |||
void *userData, RtAudio::StreamOptions *options ); | |||
void *userData, RtAudio::StreamOptions *options, | |||
RtAudioErrorCallback errorCallback ); | |||
virtual void closeStream( void ); | |||
virtual void startStream( void ) = 0; | |||
virtual void stopStream( void ) = 0; | |||
@@ -586,9 +630,9 @@ public: | |||
long getStreamLatency( void ); | |||
unsigned int getStreamSampleRate( void ); | |||
virtual double getStreamTime( void ); | |||
bool isStreamOpen( void ) const { return stream_.state != STREAM_CLOSED; }; | |||
bool isStreamRunning( void ) const { return stream_.state == STREAM_RUNNING; }; | |||
void showWarnings( bool value ) { showWarnings_ = value; }; | |||
bool isStreamOpen( void ) const { return stream_.state != STREAM_CLOSED; } | |||
bool isStreamRunning( void ) const { return stream_.state == STREAM_RUNNING; } | |||
void showWarnings( bool value ) { showWarnings_ = value; } | |||
protected: | |||
@@ -655,6 +699,7 @@ protected: | |||
:apiHandle(0), deviceBuffer(0) { device[0] = 11111; device[1] = 11111; } | |||
}; | |||
typedef S24 Int24; | |||
typedef signed short Int16; | |||
typedef signed int Int32; | |||
typedef float Float32; | |||
@@ -726,7 +771,7 @@ inline void RtAudio :: abortStream( void ) { return rtapi_->abortStream(); } | |||
inline bool RtAudio :: isStreamOpen( void ) const throw() { return rtapi_->isStreamOpen(); } | |||
inline bool RtAudio :: isStreamRunning( void ) const throw() { return rtapi_->isStreamRunning(); } | |||
inline long RtAudio :: getStreamLatency( void ) { return rtapi_->getStreamLatency(); } | |||
inline unsigned int RtAudio :: getStreamSampleRate( void ) { return rtapi_->getStreamSampleRate(); }; | |||
inline unsigned int RtAudio :: getStreamSampleRate( void ) { return rtapi_->getStreamSampleRate(); } | |||
inline double RtAudio :: getStreamTime( void ) { return rtapi_->getStreamTime(); } | |||
inline void RtAudio :: showWarnings( bool value ) throw() { rtapi_->showWarnings( value ); } | |||
@@ -742,7 +787,7 @@ public: | |||
RtApiCore(); | |||
~RtApiCore(); | |||
RtAudio::Api getCurrentApi( void ) { return RtAudio::MACOSX_CORE; }; | |||
RtAudio::Api getCurrentApi( void ) { return RtAudio::MACOSX_CORE; } | |||
unsigned int getDeviceCount( void ); | |||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); | |||
unsigned int getDefaultOutputDevice( void ); | |||
@@ -780,7 +825,7 @@ public: | |||
RtApiJack(); | |||
~RtApiJack(); | |||
RtAudio::Api getCurrentApi( void ) { return RtAudio::UNIX_JACK; }; | |||
RtAudio::Api getCurrentApi( void ) { return RtAudio::UNIX_JACK; } | |||
unsigned int getDeviceCount( void ); | |||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); | |||
void closeStream( void ); | |||
@@ -813,7 +858,7 @@ public: | |||
RtApiAsio(); | |||
~RtApiAsio(); | |||
RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_ASIO; }; | |||
RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_ASIO; } | |||
unsigned int getDeviceCount( void ); | |||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); | |||
void closeStream( void ); | |||
@@ -849,7 +894,7 @@ public: | |||
RtApiDs(); | |||
~RtApiDs(); | |||
RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_DS; }; | |||
RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_DS; } | |||
unsigned int getDeviceCount( void ); | |||
unsigned int getDefaultOutputDevice( void ); | |||
unsigned int getDefaultInputDevice( void ); | |||
@@ -871,6 +916,7 @@ public: | |||
bool coInitialized_; | |||
bool buffersRolling; | |||
long duplexPrerollBytes; | |||
std::vector<struct DsDevice> dsDevices; | |||
bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, | |||
unsigned int firstChannel, unsigned int sampleRate, | |||
RtAudioFormat format, unsigned int *bufferSize, | |||
@@ -887,7 +933,7 @@ public: | |||
RtApiAlsa(); | |||
~RtApiAlsa(); | |||
RtAudio::Api getCurrentApi() { return RtAudio::LINUX_ALSA; }; | |||
RtAudio::Api getCurrentApi() { return RtAudio::LINUX_ALSA; } | |||
unsigned int getDeviceCount( void ); | |||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); | |||
void closeStream( void ); | |||
@@ -919,7 +965,7 @@ class RtApiPulse: public RtApi | |||
{ | |||
public: | |||
~RtApiPulse(); | |||
RtAudio::Api getCurrentApi() { return RtAudio::LINUX_PULSE; }; | |||
RtAudio::Api getCurrentApi() { return RtAudio::LINUX_PULSE; } | |||
unsigned int getDeviceCount( void ); | |||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); | |||
void closeStream( void ); | |||
@@ -953,7 +999,7 @@ public: | |||
RtApiOss(); | |||
~RtApiOss(); | |||
RtAudio::Api getCurrentApi() { return RtAudio::LINUX_OSS; }; | |||
RtAudio::Api getCurrentApi() { return RtAudio::LINUX_OSS; } | |||
unsigned int getDeviceCount( void ); | |||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); | |||
void closeStream( void ); | |||
@@ -983,21 +1029,21 @@ class RtApiDummy: public RtApi | |||
{ | |||
public: | |||
RtApiDummy() { errorText_ = "RtApiDummy: This class provides no functionality."; error( RtError::WARNING ); }; | |||
RtAudio::Api getCurrentApi( void ) { return RtAudio::RTAUDIO_DUMMY; }; | |||
unsigned int getDeviceCount( void ) { return 0; }; | |||
RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) { RtAudio::DeviceInfo info; return info; }; | |||
void closeStream( void ) {}; | |||
void startStream( void ) {}; | |||
void stopStream( void ) {}; | |||
void abortStream( void ) {}; | |||
RtApiDummy() { errorText_ = "RtApiDummy: This class provides no functionality."; error( RtError::WARNING ); } | |||
RtAudio::Api getCurrentApi( void ) { return RtAudio::RTAUDIO_DUMMY; } | |||
unsigned int getDeviceCount( void ) { return 0; } | |||
RtAudio::DeviceInfo getDeviceInfo( unsigned int /*device*/ ) { RtAudio::DeviceInfo info; return info; } | |||
void closeStream( void ) {} | |||
void startStream( void ) {} | |||
void stopStream( void ) {} | |||
void abortStream( void ) {} | |||
private: | |||
bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, | |||
unsigned int firstChannel, unsigned int sampleRate, | |||
RtAudioFormat format, unsigned int *bufferSize, | |||
RtAudio::StreamOptions *options ) { return false; }; | |||
bool probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/, | |||
unsigned int /*firstChannel*/, unsigned int /*sampleRate*/, | |||
RtAudioFormat /*format*/, unsigned int * /*bufferSize*/, | |||
RtAudio::StreamOptions * /*options*/ ) { return false; } | |||
}; | |||
#endif | |||
@@ -3,7 +3,7 @@ | |||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 | |||
# Free Software Foundation, Inc. | |||
timestamp='2004-02-26' | |||
timestamp='2012-11-19' | |||
# This file is (in principle) common to ALL GNU software. | |||
# The presence of a machine in this file suggests that SOME GNU software | |||
@@ -225,7 +225,7 @@ case $basic_machine in | |||
| alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ | |||
| alphaev6[78] \ | |||
| we32k | ns16k | clipper | i370 | sh | sh[34] \ | |||
| powerpc | powerpcle \ | |||
| powerpc | powerpc64 | powerpcle \ | |||
| 1750a | dsp16xx | pdp10 | pdp11 \ | |||
| mips16 | mips64 | mipsel | mips64el \ | |||
| mips64orion | mips64orionel | mipstx39 | mipstx39el \ | |||
@@ -271,7 +271,7 @@ case $basic_machine in | |||
| alphaev6[78]-* \ | |||
| we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ | |||
| clipper-* | orion-* \ | |||
| sparclite-* | pdp10-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ | |||
| sparclite-* | pdp10-* | pdp11-* | sh-* | powerpc-* | powerpc64-* | powerpcle-* \ | |||
| sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \ | |||
| mips16-* | mips64-* | mipsel-* \ | |||
| mips64el-* | mips64orion-* | mips64orionel-* \ | |||
@@ -721,6 +721,10 @@ case $basic_machine in | |||
;; | |||
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` | |||
;; | |||
ppc64) basic_machine=powerpc64-unknown | |||
;; | |||
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` | |||
;; | |||
ppcle | powerpclittle | ppc-le | powerpc-little) | |||
basic_machine=powerpcle-unknown | |||
;; | |||
@@ -2,11 +2,25 @@ | |||
AC_INIT(RtAudio, 4.0, gary@music.mcgill.ca, rtaudio) | |||
AC_CONFIG_AUX_DIR(config) | |||
AC_CONFIG_SRCDIR(RtAudio.cpp) | |||
AC_CONFIG_FILES([rtaudio-config Makefile tests/Makefile]) | |||
AC_CONFIG_FILES([rtaudio-config librtaudio.pc Makefile tests/Makefile]) | |||
# Fill GXX with something before test. | |||
AC_SUBST( GXX, ["no"] ) | |||
dnl Check for pkg-config program, used for configuring some libraries. | |||
m4_define_default([PKG_PROG_PKG_CONFIG], | |||
[AC_MSG_CHECKING([pkg-config]) | |||
AC_MSG_RESULT([no])]) | |||
PKG_PROG_PKG_CONFIG | |||
dnl If the pkg-config autoconf support isn't installed, define its | |||
dnl autoconf macro to disable any packages depending on it. | |||
m4_define_default([PKG_CHECK_MODULES], | |||
[AC_MSG_CHECKING([$1]) | |||
AC_MSG_RESULT([no]) | |||
$4]) | |||
# Checks for programs. | |||
AC_PROG_CXX(g++ CC c++ cxx) | |||
AC_PROG_RANLIB | |||
@@ -58,6 +72,7 @@ esac | |||
# Checks for package options and external software | |||
AC_SUBST( api, [""] ) | |||
AC_SUBST( req, [""] ) | |||
AC_MSG_CHECKING(for audio API) | |||
case $host in | |||
*-*-netbsd*) | |||
@@ -77,14 +92,17 @@ case $host in | |||
# Look for ALSA flag | |||
AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA API support (linux only)], [ | |||
api="$api -D__LINUX_ALSA__" | |||
req="$req alsa" | |||
AC_MSG_RESULT(using ALSA) | |||
AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(ALSA support requires the asound library!))], ) | |||
# Look for PULSE flag | |||
AC_ARG_WITH(pulse, [ --with-pulse = choose PulseAudio API support (linux only)], [ | |||
api="$api -D__LINUX_PULSE__" | |||
req="$req libpulse-simple" | |||
AC_MSG_RESULT(using PulseAudio) | |||
AC_CHECK_LIB(pulse-simple, pa_simple_new, , AC_MSG_ERROR(PulseAudio support requires the pulse-simple library!))], ) | |||
PKG_CHECK_MODULES([PULSE], [libpulse-simple], , AC_MSG_ERROR(PulseAudio support requires the pulse-simple library!)) | |||
LIBS="$LIBS `pkg-config --libs libpulse-simple`" ], ) | |||
# Look for OSS flag | |||
AC_ARG_WITH(oss, [ --with-oss = choose OSS API support (linux only)], [ | |||
@@ -95,6 +113,7 @@ case $host in | |||
if [test "$api" == "";] then | |||
AC_MSG_RESULT(using ALSA) | |||
AC_SUBST( api, [-D__LINUX_ALSA__] ) | |||
req="$req alsa" | |||
AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(ALSA support requires the asound library!)) | |||
fi | |||
@@ -31,7 +31,7 @@ PROJECT_NAME = RtAudio | |||
# This could be handy for archiving the generated documentation or | |||
# if some version control system is used. | |||
PROJECT_NUMBER = 4.0.11 | |||
PROJECT_NUMBER = 4.0.12 | |||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) | |||
# base path where the generated documentation will be put. | |||
@@ -32,7 +32,7 @@ In order to compile RtAudio for a specific OS and audio API, it is necessary to | |||
<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</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> | |||
@@ -1,7 +1,7 @@ | |||
<HR> | |||
<table><tr><td><img src="../images/mcgill.gif" width=165></td> | |||
<td>©2001-2012 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> | |||
<td>©2001-2013 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> | |||
@@ -15,24 +15,21 @@ RtAudio is a set of C++ classes that provide a common API (Application Programmi | |||
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 What's New (Version 4.0) | |||
RtAudio V4 represents a significant rewrite of the code and includes a number of API and functionality changes from previous versions. A partial list of the changes includes: | |||
- 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 | |||
- updated support for OSS version 4.0 | |||
- discontinued support of blocking functionality | |||
- discontinued support of SGI | |||
Devices are now re-enumerated every time the RtAudio::getDeviceCount(), RtAudio::getDeviceInfo(), and RtAudio::openStream() functions are called. This allows for the proper identification of hot-pluggable (USB, Firewire, ...) devices that are connected after an RtAudio instance is created. | |||
\section whatsnew Latest Updates (Version 4.0.12) | |||
- 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) | |||
\section download Download | |||
Latest Release (14 June 2012): <A href="http://www.music.mcgill.ca/~gary/rtaudio/release/rtaudio-4.0.11.tar.gz">Version 4.0.11</A> | |||
Latest Release (16 April 2013): <A href="http://www.music.mcgill.ca/~gary/rtaudio/release/rtaudio-4.0.12.tar.gz">Version 4.0.12</A> | |||
\section documentation Documentation Links | |||
@@ -1,6 +1,17 @@ | |||
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 and ASIO) operating systems. | |||
By Gary P. Scavone, 2001-2012. | |||
By Gary P. Scavone, 2001-2013. | |||
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) | |||
@@ -1,268 +1,308 @@ | |||
#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; | |||
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++,(LPTSTR)databuf,512); | |||
if (cr == ERROR_SUCCESS) { | |||
CharLowerBuff(databuf,strlen(databuf)); | |||
if (!(strcmp(databuf,clsidstr))) { | |||
if ((cr = RegOpenKeyEx(hkEnum,(LPCTSTR)databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) { | |||
if ((cr = RegOpenKeyEx(hksub,(LPCTSTR)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); | |||
} | |||
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 = RegOpenKeyEx(hkey,(LPCTSTR)keyname,0,KEY_READ,&hksub)) == ERROR_SUCCESS) { | |||
datatype = REG_SZ; datasize = 256; | |||
cr = RegQueryValueEx(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 = RegQueryValueEx(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; | |||
BOOL fin = FALSE; | |||
numdrv = 0; | |||
lpdrvlist = 0; | |||
cr = RegOpenKey(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum); | |||
while (cr == ERROR_SUCCESS) { | |||
if ((cr = RegEnumKey(hkEnum,index++,(LPTSTR)keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) { | |||
lpdrvlist = newDrvStruct (hkEnum,keyname,0,lpdrvlist); | |||
} | |||
else fin = TRUE; | |||
} | |||
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; | |||
} | |||
#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; | |||
BOOL fin = FALSE; | |||
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); | |||
} | |||
else fin = TRUE; | |||
} | |||
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; | |||
} | |||
@@ -1,6 +1,6 @@ | |||
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 and ASIO) operating systems. | |||
By Gary P. Scavone, 2001-2012. | |||
By Gary P. Scavone, 2001-2013. | |||
To configure and compile (on Unix systems and MinGW): | |||
@@ -30,8 +30,14 @@ If you wish to use a different compiler than that selected by configure, specify | |||
./configure CXX=CC | |||
For Windows Users: | |||
WINDOWS USERS: | |||
RtAudio compiles with the MinGW compiler or MS Visual Studio. | |||
Visual C++ 6.0 project files are included for the test programs in the /tests/Windows/ directory. These projects compile API support for both ASIO and DirectSound. Version 4.0 of RtAudio was tested with the .net compiler and it will not compile in Visual C++ 6.0 because of its non-conformance to modern C++ standards. | |||
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 both ASIO 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,12 @@ | |||
prefix=/usr/local | |||
exec_prefix=${prefix} | |||
libdir=${exec_prefix}/lib | |||
includedir=${prefix}/include | |||
Name: librtaudio | |||
Description: RtAudio - a set of C++ classes that provide a common API for realtime audio input/output | |||
Version: 4.0.12 | |||
Requires: @req@ | |||
Libs: -L${libdir} -lrtaudio | |||
Libs.private: -lpthread | |||
Cflags: -pthread -I${includedir} @CPPFLAGS@ |
@@ -1,12 +1,12 @@ | |||
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 and ASIO) operating systems. | |||
By Gary P. Scavone, 2001-2012. | |||
By Gary P. Scavone, 2001-2013. | |||
This distribution of RtAudio contains the following: | |||
doc: RtAudio documentation (see doc/html/index.html) | |||
tests: example RtAudio programs | |||
asio: header and source files necessary for ASIO compilation | |||
include: header and source files necessary for ASIO, DS & OSS compilation | |||
tests/Windows: Visual C++ .net test program workspace and projects | |||
OVERVIEW: | |||
@@ -34,7 +34,7 @@ LEGAL AND ETHICAL: | |||
The RtAudio license is similar to the MIT License. | |||
RtAudio: a set of realtime audio i/o C++ classes | |||
Copyright (c) 2001-2012 Gary P. Scavone | |||
Copyright (c) 2001-2013 Gary P. Scavone | |||
Permission is hereby granted, free of charge, to any person | |||
obtaining a copy of this software and associated documentation files | |||
@@ -20,12 +20,15 @@ int main() | |||
apiMap[RtAudio::WINDOWS_DS] = "Windows Direct Sound"; | |||
apiMap[RtAudio::UNIX_JACK] = "Jack Client"; | |||
apiMap[RtAudio::LINUX_ALSA] = "Linux ALSA"; | |||
apiMap[RtAudio::LINUX_PULSE] = "Linux PulseAudio"; | |||
apiMap[RtAudio::LINUX_OSS] = "Linux OSS"; | |||
apiMap[RtAudio::RTAUDIO_DUMMY] = "RtAudio Dummy"; | |||
std::vector< RtAudio::Api > apis; | |||
RtAudio :: getCompiledApi( apis ); | |||
std::cout << "\nRtAudio Version " << RtAudio::getVersion() << std::endl; | |||
std::cout << "\nCompiled APIs:\n"; | |||
for ( unsigned int i=0; i<apis.size(); i++ ) | |||
std::cout << " " << apiMap[ apis[i] ] << std::endl; | |||
@@ -14,24 +14,24 @@ | |||
#include <cstring> | |||
/* | |||
typedef signed long MY_TYPE; | |||
#define FORMAT RTAUDIO_SINT24 | |||
typedef char MY_TYPE; | |||
typedef char MY_TYPE; | |||
#define FORMAT RTAUDIO_SINT8 | |||
*/ | |||
typedef signed short MY_TYPE; | |||
typedef signed short MY_TYPE; | |||
#define FORMAT RTAUDIO_SINT16 | |||
/* | |||
typedef signed long MY_TYPE; | |||
typedef S24 MY_TYPE; | |||
#define FORMAT RTAUDIO_SINT24 | |||
typedef signed long MY_TYPE; | |||
#define FORMAT RTAUDIO_SINT32 | |||
typedef float MY_TYPE; | |||
typedef float MY_TYPE; | |||
#define FORMAT RTAUDIO_FLOAT32 | |||
typedef double MY_TYPE; | |||
typedef double MY_TYPE; | |||
#define FORMAT RTAUDIO_FLOAT64 | |||
*/ | |||
@@ -26,6 +26,10 @@ typedef signed short MY_TYPE; | |||
#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 | |||
@@ -13,29 +13,29 @@ | |||
#include <cstdlib> | |||
/* | |||
typedef signed long MY_TYPE; | |||
#define FORMAT RTAUDIO_SINT24 | |||
#define SCALE 2147483647.0 | |||
typedef char MY_TYPE; | |||
typedef char MY_TYPE; | |||
#define FORMAT RTAUDIO_SINT8 | |||
#define SCALE 127.0 | |||
*/ | |||
typedef signed short MY_TYPE; | |||
typedef signed short MY_TYPE; | |||
#define FORMAT RTAUDIO_SINT16 | |||
#define SCALE 32767.0 | |||
/* | |||
typedef signed long MY_TYPE; | |||
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; | |||
typedef float MY_TYPE; | |||
#define FORMAT RTAUDIO_FLOAT32 | |||
#define SCALE 1.0 | |||
typedef double MY_TYPE; | |||
typedef double MY_TYPE; | |||
#define FORMAT RTAUDIO_FLOAT64 | |||
#define SCALE 1.0 | |||
*/ | |||
@@ -88,7 +88,7 @@ int saw( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, | |||
for ( i=0; i<nBufferFrames; i++ ) { | |||
for ( j=0; j<channels; j++ ) { | |||
*buffer++ = (MY_TYPE) (lastValues[j] * SCALE); | |||
*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; | |||
} | |||
@@ -116,7 +116,7 @@ int saw( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, | |||
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); | |||
*buffer++ = (MY_TYPE) (lastValues[j] * SCALE * 0.5); | |||
lastValues[j] += increment; | |||
if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0; | |||
} | |||
@@ -163,7 +163,7 @@ int main( int argc, char *argv[] ) | |||
oParams.nChannels = channels; | |||
oParams.firstChannel = offset; | |||
options.flags |= RTAUDIO_HOG_DEVICE; | |||
options.flags = RTAUDIO_HOG_DEVICE; | |||
options.flags |= RTAUDIO_SCHEDULE_REALTIME; | |||
#if !defined( USE_INTERLEAVED ) | |||
options.flags |= RTAUDIO_NONINTERLEAVED; | |||
@@ -16,24 +16,24 @@ | |||
#include <stdio.h> | |||
/* | |||
typedef char MY_TYPE; | |||
typedef char MY_TYPE; | |||
#define FORMAT RTAUDIO_SINT8 | |||
*/ | |||
typedef signed short MY_TYPE; | |||
typedef signed short MY_TYPE; | |||
#define FORMAT RTAUDIO_SINT16 | |||
/* | |||
typedef signed long MY_TYPE; | |||
typedef S24 MY_TYPE; | |||
#define FORMAT RTAUDIO_SINT24 | |||
typedef signed long MY_TYPE; | |||
typedef signed long MY_TYPE; | |||
#define FORMAT RTAUDIO_SINT32 | |||
typedef float MY_TYPE; | |||
typedef float MY_TYPE; | |||
#define FORMAT RTAUDIO_FLOAT32 | |||
typedef double MY_TYPE; | |||
typedef double MY_TYPE; | |||
#define FORMAT RTAUDIO_FLOAT64 | |||
*/ | |||